001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.shared.converter.schema; 021 022 import java.io.ByteArrayInputStream; 023 import java.io.File; 024 import java.io.FileInputStream; 025 import java.io.IOException; 026 import java.io.InputStream; 027 import java.io.PipedInputStream; 028 import java.io.PipedOutputStream; 029 import java.io.Writer; 030 import java.text.ParseException; 031 import java.util.List; 032 033 import org.apache.directory.shared.i18n.I18n; 034 import org.apache.directory.shared.ldap.util.ExceptionUtils; 035 036 import antlr.RecognitionException; 037 import antlr.TokenStreamException; 038 039 /* 040 import java.io.ByteArrayInputStream; 041 import java.io.File; 042 import java.io.FileInputStream; 043 import java.io.IOException; 044 import java.io.InputStream; 045 import java.io.PipedInputStream; 046 import java.io.PipedOutputStream; 047 import java.io.Writer; 048 import java.text.ParseException; 049 import java.util.List; 050 051 import antlr.RecognitionException; 052 import antlr.TokenStreamException; 053 054 import org.apache.directory.shared.ldap.util.ExceptionUtils; 055 */ 056 057 058 /** 059 * A reusable wrapper for antlr generated schema parsers. 060 * 061 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 062 * @version $Rev$, $Date$ 063 */ 064 public class SchemaParser 065 { 066 /** The antlr generated parser */ 067 private antlrSchemaParser parser = null; 068 069 /** A pipe into the parser */ 070 private PipedOutputStream parserIn = null; 071 072 /** A temporary buffer storing the read schema bytes */ 073 byte[] buf = new byte[128]; 074 075 /** The inputStream mapped over the schema file to parse */ 076 private InputStream schemaIn; 077 078 /** The thread used to read the schema */ 079 private Thread producerThread; 080 081 /** 082 * Creates a reusable instance of an SchemaParser. 083 * 084 * @throws IOException if the pipe cannot be formed 085 */ 086 public SchemaParser() throws IOException 087 { 088 init(); 089 } 090 091 /** 092 * Initializes a parser and its plumbing. 093 * 094 * @throws IOException if a pipe cannot be formed. 095 */ 096 public void init() throws IOException 097 { 098 parserIn = new PipedOutputStream(); 099 PipedInputStream in = new PipedInputStream(); 100 parserIn.connect( in ); 101 antlrSchemaLexer lexer = new antlrSchemaLexer( in ); 102 parser = new antlrSchemaParser( lexer ); 103 } 104 105 /** 106 * Clear the parser. 107 */ 108 public synchronized void clear() 109 { 110 parser.clear(); 111 } 112 113 /** 114 * Thread safe method parses an OpenLDAP schemaObject element/object. 115 * 116 * @param schemaObject the String image of a complete schema object 117 */ 118 public synchronized List<SchemaElement> parse( String schemaObject ) throws IOException, ParseException 119 { 120 if ( ( schemaObject == null ) || ( schemaObject.trim().equals( "" ) ) ) 121 { 122 throw new ParseException( I18n.err( I18n.ERR_06001 ), 0 ); 123 } 124 125 schemaIn = new ByteArrayInputStream( schemaObject.getBytes() ); 126 127 if ( producerThread == null ) 128 { 129 producerThread = new Thread( new DataProducer() ); 130 } 131 132 producerThread.start(); 133 return invokeParser( schemaObject ); 134 } 135 136 /** 137 * Invoke the parser 138 * @param schemaName The schema to be parsed 139 * @return A list of schema elements 140 * 141 * @throws IOException If the inputStream can't be read 142 * @throws ParseException If the parser encounter an error 143 */ 144 private List<SchemaElement> invokeParser( String schemaName ) throws IOException, ParseException 145 { 146 try 147 { 148 parser.parseSchema(); 149 150 return parser.getSchemaElements(); 151 } 152 catch ( RecognitionException re ) 153 { 154 String msg = I18n.err( I18n.ERR_06002, schemaName, ExceptionUtils.getFullStackTrace( re ) ); 155 init(); 156 throw new ParseException( msg, re.getColumn() ); 157 } 158 catch ( TokenStreamException tse ) 159 { 160 String msg = I18n.err( I18n.ERR_06002, schemaName, ExceptionUtils.getFullStackTrace( tse ) ); 161 init(); 162 throw new ParseException( msg, 0 ); 163 } 164 } 165 166 /** 167 * Thread safe method parses a stream of OpenLDAP schemaObject elements/objects. 168 * 169 * @param schemaIn a stream of schema objects 170 */ 171 public synchronized List<SchemaElement> parse( InputStream schemaIn, Writer out ) throws IOException, ParseException 172 { 173 this.schemaIn = schemaIn; 174 175 if ( producerThread == null ) 176 { 177 producerThread = new Thread( new DataProducer() ); 178 } 179 180 producerThread.start(); 181 182 return invokeParser( "schema input stream ==> " + schemaIn.toString() ); 183 } 184 185 186 /** 187 * Thread safe method parses a file of OpenLDAP schemaObject elements/objects. 188 * 189 * @param schemaFile a file of schema objects 190 */ 191 public synchronized void parse( File schemaFile ) throws IOException, ParseException 192 { 193 this.schemaIn = new FileInputStream( schemaFile ); 194 195 if ( producerThread == null ) 196 { 197 producerThread = new Thread( new DataProducer() ); 198 } 199 200 producerThread.start(); 201 invokeParser( "schema file ==> " + schemaFile.getAbsolutePath() ); 202 } 203 204 /** 205 * The thread which read the schema files and fill the 206 * temporaru buffer used by the lexical analyzer. 207 */ 208 class DataProducer implements Runnable 209 { 210 public void run() 211 { 212 int count = -1; 213 214 try 215 { 216 while ( ( count = schemaIn.read( buf ) ) != -1 ) 217 { 218 parserIn.write( buf, 0, count ); 219 parserIn.flush(); 220 } 221 222 // using an input termination token END - need extra space to return 223 parserIn.write( "END ".getBytes() ); 224 } 225 catch ( IOException e ) 226 { 227 e.printStackTrace(); 228 } 229 } 230 } 231 }