View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server.tools.schema;
18  
19  
20  import org.apache.ldap.common.util.ExceptionUtils;
21  
22  import java.util.Map;
23  import java.text.ParseException;
24  import java.io.*;
25  
26  import antlr.RecognitionException;
27  import antlr.TokenStreamException;
28  
29  
30  /***
31   * A reusable wrapper for antlr generated OpenLDAP schema parsers.
32   *
33   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
34   * @version $Rev: 157708 $
35   */
36  public class OpenLdapSchemaParser
37  {
38      /*** the monitor to use for this parser */
39      private ParserMonitor monitor = new ParserMonitorAdapter();
40      /*** The antlr generated parser */
41      private antlrOpenLdapSchemaParser parser = null;
42      /*** A pipe into the parser */
43      private PipedOutputStream parserIn = null;
44  
45  
46      /***
47       * Creates a reusable instance of an OpenLdapSchemaParser.
48       *
49       * @throws IOException if the pipe cannot be formed
50       */
51      public OpenLdapSchemaParser() throws IOException
52      {
53          init();
54      }
55  
56  
57      /***
58       * Initializes a parser and its plumbing.
59       *
60       * @throws IOException if a pipe cannot be formed.
61       */
62      public void init() throws IOException
63      {
64          parserIn = new PipedOutputStream();
65          PipedInputStream in = new PipedInputStream();
66          parserIn.connect( in );
67          antlrOpenLdapSchemaLexer lexer = new antlrOpenLdapSchemaLexer( in );
68          parser = new antlrOpenLdapSchemaParser( lexer );
69      }
70  
71  
72      public synchronized void clear()
73      {
74          parser.clear();
75      }
76  
77  
78      public Map getAttributeTypes()
79      {
80          return parser.getAttributeTypes();
81      }
82  
83  
84      public Map getObjectClassTypes()
85      {
86          return parser.getObjectClasses();
87      }
88  
89  
90      /***
91       * Thread safe method parses an OpenLDAP schemaObject element/object.
92       *
93       * @param schemaObject the String image of a complete schema object
94       */
95      public synchronized void parse( String schemaObject ) throws IOException, ParseException
96      {
97          if ( schemaObject == null || schemaObject.trim().equals( "" ) )
98          {
99              throw new ParseException( "The schemaObject is either null or is "
100                 + "the empty String!", 0 );
101         }
102 
103         this.schemaIn = new ByteArrayInputStream( schemaObject.getBytes() );
104 
105         if ( producerThread == null )
106         {
107             producerThread = new Thread( new DataProducer() );
108         }
109 
110         producerThread.start();
111         invokeParser( schemaObject );
112     }
113 
114 
115     private void invokeParser( String subject ) throws IOException, ParseException
116     {
117         try
118         {
119             monitor.startedParse( "starting parse on:\n" + subject );
120             parser.parseSchema();
121             monitor.finishedParse( "Done parsing!" );
122         }
123         catch ( RecognitionException e )
124         {
125             String msg = "Parser failure on:\n\t" + subject ;
126             msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e );
127             init();
128             throw new ParseException( msg, e.getColumn() );
129         }
130         catch ( TokenStreamException e2 )
131         {
132             String msg = "Parser failure on:\n\t" + subject ;
133             msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e2 );
134             init();
135             throw new ParseException( msg, 0 );
136         }
137     }
138 
139 
140     byte[] buf = new byte[128];
141     private InputStream schemaIn;
142     private Thread producerThread;
143 
144     /***
145      * Thread safe method parses a stream of OpenLDAP schemaObject elements/objects.
146      *
147      * @param schemaIn a stream of schema objects
148      */
149     public synchronized void parse( InputStream schemaIn ) throws IOException, ParseException
150     {
151         this.schemaIn = schemaIn;
152 
153         if ( producerThread == null )
154         {
155             producerThread = new Thread( new DataProducer() );
156         }
157 
158         producerThread.start();
159         invokeParser( "schema input stream ==> " + schemaIn.toString() );
160     }
161 
162 
163     /***
164      * Thread safe method parses a file of OpenLDAP schemaObject elements/objects.
165      *
166      * @param schemaFile a file of schema objects
167      */
168     public synchronized void parse( File schemaFile ) throws IOException, ParseException
169     {
170         this.schemaIn = new FileInputStream( schemaFile );
171 
172         if ( producerThread == null )
173         {
174             producerThread = new Thread( new DataProducer() );
175         }
176 
177         producerThread.start();
178         invokeParser( "schema file ==> " + schemaFile.getAbsolutePath() );
179     }
180 
181 
182     public void setParserMonitor( ParserMonitor monitor )
183     {
184         this.monitor = monitor ;
185         this.parser.setParserMonitor( monitor );
186     }
187 
188 
189     class DataProducer implements Runnable
190     {
191         public void run()
192         {
193             int count = -1;
194 
195             try
196             {
197                 while ( ( count = schemaIn.read( buf ) ) != -1 )
198                 {
199                     parserIn.write( buf, 0, count );
200                     parserIn.flush();
201                 }
202 
203                 // using an input termination token END - need extra space to return
204                 parserIn.write( "END ".getBytes() );
205             }
206             catch ( IOException e )
207             {
208                 e.printStackTrace();
209             }
210         }
211     }
212 }