001: /*
002: * $Id: EntityManager.java,v 1.6 2004/07/11 09:37:37 yuvalo Exp $
003: *
004: * (C) Copyright 2002-2004 by Yuval Oren. All rights reserved.
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * 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, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: package com.bluecast.xml;
020:
021: import java.util.*;
022: import java.io.*;
023: import java.net.*;
024:
025: import com.bluecast.util.*;
026: import org.xml.sax.*;
027:
028: public class EntityManager {
029: // Entity types
030: static public final int GENERAL = 0;
031: static public final int PARAMETER = 1;
032:
033: final private class Entry implements Entity {
034: boolean isOpen = false;
035: char[] value;
036: String pubID, sysID, ndata;
037: XMLInputReader reader = null;
038: boolean isStandalone = false;
039:
040: Entry(String value) {
041: pubID = sysID = ndata = null;
042: this .value = value.toCharArray();
043: }
044:
045: Entry(String pubID, String sysID) {
046: this (pubID, sysID, null);
047: }
048:
049: Entry(String pubID, String sysID, String ndata) {
050: this .pubID = pubID;
051: this .sysID = sysID;
052: this .ndata = ndata;
053: }
054:
055: public void open() throws RecursionException, SAXException,
056: IOException {
057:
058: if (ndata != null) {
059: throw new FatalParsingException(
060: "Cannot reference entity; unknown NDATA type '"
061: + ndata + "'");
062: }
063:
064: if (isOpen)
065: throw new RecursionException();
066:
067: if (!isInternal()) {
068: if (resolver == null) {
069: reader = new XMLStreamReader((new URL(sysID))
070: .openStream(), true);
071: } else {
072: InputSource source = resolver.resolveEntity(pubID,
073: sysID);
074: if (source == null) {
075: reader = new XMLStreamReader((new URL(sysID))
076: .openStream(), true);
077: } else {
078: Reader r = source.getCharacterStream();
079: if (r != null)
080: reader = new XMLReaderReader(r, true);
081: else {
082: InputStream in;
083:
084: in = source.getByteStream();
085: if (in != null)
086: reader = new XMLStreamReader(in, source
087: .getEncoding(), true);
088: else
089: reader = new XMLStreamReader((new URL(
090: source.getSystemId()))
091: .openStream(), source
092: .getEncoding(), true);
093: }
094: }
095: }
096: isStandalone = reader.isXMLStandalone();
097: }
098: isOpen = true;
099: }
100:
101: public boolean isOpen() {
102: return isOpen;
103: }
104:
105: public void close() {
106: isOpen = false;
107: reader = null;
108: }
109:
110: public String getSystemID() {
111: return sysID;
112: }
113:
114: public String getPublicID() {
115: return pubID;
116: }
117:
118: public boolean isStandalone() {
119: return isStandalone;
120: }
121:
122: public void setStandalone(boolean standalone) {
123: isStandalone = standalone;
124: }
125:
126: public boolean isInternal() {
127: return (sysID == null);
128: }
129:
130: public boolean isParsed() {
131: return (ndata == null);
132: }
133:
134: public String getDeclaredEncoding() {
135: if (reader != null)
136: return reader.getXMLDeclaredEncoding();
137: else
138: return null;
139: }
140:
141: public boolean isStandaloneDeclared() {
142: if (reader != null)
143: return reader.isXMLStandaloneDeclared();
144: else
145: return false;
146: }
147:
148: public String getXMLVersion() {
149: if (reader != null)
150: return reader.getXMLVersion();
151: else
152: return null;
153: }
154:
155: public Reader getReader() {
156: if (isInternal())
157: return new CharArrayReader(value);
158: else
159: return reader;
160: }
161:
162: public String stringValue() {
163: return new String(value);
164: }
165:
166: public char[] charArrayValue() {
167: return value;
168: }
169:
170: }
171:
172: private EntityResolver resolver;
173: private Map[] entityMaps = new HashMap[] { new HashMap(),
174: new HashMap() };
175: private Map entitiesByURI = new HashMap();
176:
177: public EntityManager() {
178: this (null);
179: }
180:
181: public EntityManager(EntityResolver resolver) {
182: setResolver(resolver);
183: }
184:
185: public void setResolver(EntityResolver resolver) {
186: this .resolver = resolver;
187: }
188:
189: public EntityResolver getResolver() {
190: return resolver;
191: }
192:
193: /**
194: * Defines an internal entity. Returns true if successful,
195: * false if the entity was already defined.
196: */
197: public boolean putInternal(String name, String value, int type) {
198: if (entityMaps[type].get(name) == null) {
199: entityMaps[type].put(name, new Entry(value));
200: return true;
201: }
202:
203: return false;
204: }
205:
206: /**
207: * Defines an external entity. Returns true if successful,
208: * false if the entity was already defined.
209: */
210: public boolean putExternal(Entity context, String name,
211: String pubID, String sysID, int type)
212: throws MalformedURLException {
213:
214: if (entityMaps[type].get(name) == null) {
215: // First we resolve the sysID in context of the entity
216: sysID = resolveSystemID(context.getSystemID(), sysID);
217:
218: // TODO: perhaps we should do this with pubID too
219:
220: Entry e = new Entry(pubID, sysID);
221: entityMaps[type].put(name, e);
222: if (pubID != null && pubID.length() > 0)
223: entitiesByURI.put(pubID, e);
224: entitiesByURI.put(sysID, e);
225: return true;
226: }
227:
228: return false;
229: }
230:
231: /**
232: * Defines an unparsed entity. Returns true if successful,
233: * false if the entity was already defined.
234: */
235:
236: public boolean putUnparsed(Entity context, String name,
237: String pubID, String sysID, String ndata, int type)
238: throws MalformedURLException {
239:
240: if (entityMaps[type].get(name) == null) {
241:
242: // TODO should unparsed entity system ID's be resolved?
243: //sysID = resolveSystemID(context.getSystemID(),sysID);
244: entityMaps[type].put(name, new Entry(pubID, sysID, ndata));
245: return true;
246: }
247:
248: return false;
249: }
250:
251: public void clear() {
252: entityMaps[GENERAL].clear();
253: entityMaps[PARAMETER].clear();
254: entitiesByURI.clear();
255: }
256:
257: public Entity getByName(String name, int type) {
258: return (Entry) entityMaps[type].get(name);
259: }
260:
261: public Entity getByID(Entity context, String pubID, String sysID)
262: throws MalformedURLException {
263: Entity result = null;
264:
265: sysID = resolveSystemID(context.getSystemID(), sysID);
266:
267: result = (Entity) entitiesByURI.get(sysID);
268: if (result != null)
269: return result;
270:
271: if (pubID != null && pubID.length() > 0) {
272: result = (Entity) entitiesByURI.get(pubID);
273: if (result != null)
274: return result;
275: }
276:
277: // No entity exists for this URI; create one
278: result = new Entry(pubID, sysID);
279: if (pubID != null && pubID.length() > 0)
280: entitiesByURI.put(pubID, result);
281: entitiesByURI.put(sysID, result);
282:
283: return result;
284: }
285:
286: static public String resolveSystemID(String contextSysID,
287: String sysID) throws MalformedURLException {
288: URL url;
289: if (contextSysID != null)
290: url = new URL(new URL(contextSysID), sysID);
291: else
292: url = new URL(sysID);
293:
294: return url.toString();
295: }
296:
297: }
|