1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.schema;
21
22
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InvalidObjectException;
28 import java.nio.file.Files;
29 import java.util.Map;
30 import java.util.TreeMap;
31 import java.util.UUID;
32 import java.util.regex.Pattern;
33
34 import org.apache.directory.api.i18n.I18n;
35 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
36 import org.apache.directory.api.ldap.model.csn.Csn;
37 import org.apache.directory.api.ldap.model.csn.CsnFactory;
38 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
39 import org.apache.directory.api.ldap.model.entry.Entry;
40 import org.apache.directory.api.ldap.model.exception.LdapException;
41 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
42 import org.apache.directory.api.ldap.model.ldif.LdifEntry;
43 import org.apache.directory.api.ldap.model.ldif.LdifReader;
44 import org.apache.directory.api.ldap.model.name.Dn;
45 import org.apache.directory.api.ldap.model.schema.SchemaManager;
46 import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
47 import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
48 import org.apache.directory.api.ldap.schema.extractor.impl.ResourceMap;
49 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
50 import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
51 import org.apache.directory.server.core.api.partition.Partition;
52 import org.apache.directory.server.core.api.partition.PartitionTxn;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56
57
58
59
60
61
62 public class SchemaLdifToPartitionExtractor implements SchemaLdifExtractor
63 {
64
65 private static final Logger LOG = LoggerFactory.getLogger( SchemaLdifToPartitionExtractor.class );
66
67
68
69
70
71 private static final Pattern EXTRACT_PATTERN = Pattern.compile( ".*schema" + "[/\\Q\\\\E]" + "ou=schema.*\\.ldif" );
72
73 private final CsnFactory csnFactory = new CsnFactory( 0 );
74
75
76 private boolean extracted;
77
78 private final SchemaManager schemaManager;
79 private final Partition partition;
80
81
82
83
84
85
86
87
88
89
90 public SchemaLdifToPartitionExtractor( SchemaManager schemaManager, Partition partition ) throws LdapException
91 {
92 this.schemaManager = schemaManager;
93 this.partition = partition;
94
95 Dn dn = new Dn( schemaManager, SchemaConstants.OU_SCHEMA );
96 HasEntryOperationContextcontext/HasEntryOperationContext.html#HasEntryOperationContext">HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( null, dn );
97 hasEntryContext.setPartition( partition );
98
99 try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
100 {
101 hasEntryContext.setTransaction( partitionTxn );
102
103 if ( partition.hasEntry( hasEntryContext ) )
104 {
105 LOG.info( "Schema entry 'ou=schema' exists: extracted state set to true." );
106 extracted = true;
107 }
108 else
109 {
110 LOG.info( "Schema entry 'ou=schema' does NOT exist: extracted state set to false." );
111 extracted = false;
112 }
113 }
114 catch ( IOException ioe )
115 {
116 throw new LdapOtherException( ioe.getMessage(), ioe );
117 }
118 }
119
120
121
122
123
124
125
126 @Override
127 public boolean isExtracted()
128 {
129 return extracted;
130 }
131
132
133
134
135
136 @Override
137 public void extractOrCopy( boolean overwrite ) throws IOException
138 {
139 Map<String, Boolean> resources = ResourceMap.getResources( EXTRACT_PATTERN );
140
141
142 resources = new TreeMap<>( resources );
143
144 if ( !extracted || overwrite )
145 {
146 for ( Map.Entry<String, Boolean> entry : resources.entrySet() )
147 {
148 if ( entry.getValue() )
149 {
150 addFromClassLoader( entry.getKey() );
151 }
152 else
153 {
154 File resource = new File( entry.getKey() );
155 addLdifFile( resource );
156 }
157 }
158
159 extracted = true;
160 }
161 }
162
163
164
165
166
167 @Override
168 public void extractOrCopy() throws IOException
169 {
170 extractOrCopy( false );
171 }
172
173
174
175
176
177
178
179
180 private void addLdifFile( File source ) throws IOException
181 {
182 LOG.debug( "copyFile(): source = {}", source );
183
184 if ( !source.getParentFile().exists() )
185 {
186 throw new FileNotFoundException( I18n.err( I18n.ERR_16002_MORE_THAN_ONE_ENTRY, source.getAbsolutePath() ) );
187 }
188
189 InputStream in = Files.newInputStream( source.toPath() );
190 addFromStream( in, source.getAbsolutePath() );
191 }
192
193
194
195
196
197
198
199
200 private void addFromClassLoader( String resource ) throws IOException
201 {
202 InputStream in = DefaultSchemaLdifExtractor.getUniqueResourceAsStream( resource,
203 "LDIF file in schema repository" );
204 addFromStream( in, resource );
205 }
206
207
208
209
210
211
212
213
214
215 private void addFromStream( InputStream in, String source ) throws IOException
216 {
217 try
218 {
219 LdifReader ldifReader = new LdifReader( in );
220 boolean first = true;
221 LdifEntry ldifEntry = null;
222
223 try
224 {
225 while ( ldifReader.hasNext() )
226 {
227 if ( first )
228 {
229 ldifEntry = ldifReader.next();
230
231 if ( ldifEntry.get( SchemaConstants.ENTRY_UUID_AT ) == null )
232 {
233
234 UUID entryUuid = UUID.randomUUID();
235 ldifEntry.addAttribute( SchemaConstants.ENTRY_UUID_AT, entryUuid.toString() );
236 }
237 if ( ldifEntry.get( SchemaConstants.ENTRY_CSN_AT ) == null )
238 {
239
240 Csn csn = csnFactory.newInstance();
241 ldifEntry.addAttribute( SchemaConstants.ENTRY_CSN_AT, csn.toString() );
242 }
243
244 first = false;
245 }
246 else
247 {
248
249 String msg = I18n.err( I18n.ERR_16002_MORE_THAN_ONE_ENTRY, source );
250 LOG.error( msg );
251 throw new InvalidObjectException( msg );
252 }
253 }
254 }
255 finally
256 {
257 ldifReader.close();
258 }
259
260
261 if ( ldifEntry != null )
262 {
263 Entry entry = new DefaultEntry( schemaManager, ldifEntry.getEntry() );
264 AddOperationContextterceptor/context/AddOperationContext.html#AddOperationContext">AddOperationContext addContext = new AddOperationContext( null, entry );
265 addContext.setPartition( partition );
266
267 PartitionTxn partitionTxn = null;
268
269 try
270 {
271 partitionTxn = partition.beginWriteTransaction();
272 addContext.setTransaction( partitionTxn );
273
274 partition.add( addContext );
275 partitionTxn.commit();
276 }
277 catch ( LdapException le )
278 {
279 if ( partitionTxn != null )
280 {
281 try
282 {
283 partitionTxn.abort();
284 }
285 catch ( IOException ioe )
286 {
287 throw new LdapOtherException( ioe.getMessage(), ioe );
288 }
289 }
290
291 throw le;
292 }
293 catch ( IOException ioe )
294 {
295 try
296 {
297 partitionTxn.abort();
298 }
299 catch ( IOException ioe2 )
300 {
301 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
302 }
303
304 throw new LdapOtherException( ioe.getMessage(), ioe );
305 }
306 }
307 }
308 catch ( LdapException ne )
309 {
310 String msg = I18n.err( I18n.ERR_16003_ERROR_PARSING_LDIF, source, ne.getLocalizedMessage() );
311 LOG.error( msg );
312 throw new InvalidObjectException( msg );
313 }
314 }
315
316 }