001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components;
018:
019: import org.apache.avalon.framework.component.ComponentManager;
020: import org.apache.cocoon.Processor;
021: import org.apache.cocoon.environment.Environment;
022: import org.apache.cocoon.xml.XMLConsumer;
023:
024: import org.apache.commons.collections.ArrayStack;
025: import org.xml.sax.Attributes;
026: import org.xml.sax.Locator;
027: import org.xml.sax.SAXException;
028:
029: /**
030: * The stack for the processing environment.
031: * This is a special implementation of a stack for the handling of the
032: * cocoon protocol.
033: *
034: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
035: * @version CVS $Id: EnvironmentStack.java 433543 2006-08-22 06:22:54Z crossley $
036: */
037: final class EnvironmentStack extends ArrayStack {
038:
039: int offset;
040:
041: int getOffset() {
042: return this .offset;
043: }
044:
045: void setOffset(int value) {
046: this .offset = value;
047: }
048:
049: Item getCurrent() {
050: return (Item) this .get(offset);
051: }
052:
053: public Object clone() {
054: EnvironmentStack old = (EnvironmentStack) super .clone();
055: old.offset = offset;
056: return old;
057: }
058:
059: XMLConsumer getEnvironmentAwareConsumerWrapper(
060: XMLConsumer consumer, int oldOffset) {
061: return new EnvironmentChanger(consumer, this , oldOffset,
062: this .offset);
063: }
064:
065: static final class Item {
066: public final Environment env;
067: public final Processor processor;
068: public final ComponentManager manager;
069: public final int offset;
070:
071: public Item(Environment env, Processor processor,
072: ComponentManager manager, int offset) {
073: this .env = env;
074: this .processor = processor;
075: this .manager = manager;
076: this .offset = offset;
077: }
078: }
079: }
080:
081: /**
082: * This class is an {@link XMLConsumer} that changes the current environment.
083: * When a pipeline calls an internal pipeline, two environments are
084: * established: one for the calling pipeline and one for the internal pipeline.
085: * Now, if SAX events are send from the internal pipeline, they are
086: * received by some component of the calling pipeline, so inbetween we
087: * have to change the environment forth and back.
088: */
089: final class EnvironmentChanger implements XMLConsumer {
090:
091: final XMLConsumer consumer;
092: final EnvironmentStack stack;
093: final int oldOffset;
094: final int newOffset;
095:
096: EnvironmentChanger(XMLConsumer consumer, EnvironmentStack es,
097: int oldOffset, int newOffset) {
098: this .consumer = consumer;
099: this .stack = es;
100: this .oldOffset = oldOffset;
101: this .newOffset = newOffset;
102: }
103:
104: public void setDocumentLocator(Locator locator) {
105: this .stack.setOffset(this .oldOffset);
106: this .consumer.setDocumentLocator(locator);
107: this .stack.setOffset(this .newOffset);
108: }
109:
110: public void startDocument() throws SAXException {
111: this .stack.setOffset(this .oldOffset);
112: this .consumer.startDocument();
113: this .stack.setOffset(this .newOffset);
114: }
115:
116: public void endDocument() throws SAXException {
117: this .stack.setOffset(this .oldOffset);
118: this .consumer.endDocument();
119: this .stack.setOffset(this .newOffset);
120: }
121:
122: public void startPrefixMapping(String prefix, String uri)
123: throws SAXException {
124: this .stack.setOffset(this .oldOffset);
125: this .consumer.startPrefixMapping(prefix, uri);
126: this .stack.setOffset(this .newOffset);
127: }
128:
129: public void endPrefixMapping(String prefix) throws SAXException {
130: this .stack.setOffset(this .oldOffset);
131: this .consumer.endPrefixMapping(prefix);
132: this .stack.setOffset(this .newOffset);
133: }
134:
135: public void startElement(String uri, String loc, String raw,
136: Attributes a) throws SAXException {
137: this .stack.setOffset(this .oldOffset);
138: this .consumer.startElement(uri, loc, raw, a);
139: this .stack.setOffset(this .newOffset);
140: }
141:
142: public void endElement(String uri, String loc, String raw)
143: throws SAXException {
144: this .stack.setOffset(this .oldOffset);
145: this .consumer.endElement(uri, loc, raw);
146: this .stack.setOffset(this .newOffset);
147: }
148:
149: public void characters(char c[], int start, int len)
150: throws SAXException {
151: this .stack.setOffset(this .oldOffset);
152: this .consumer.characters(c, start, len);
153: this .stack.setOffset(this .newOffset);
154: }
155:
156: public void ignorableWhitespace(char c[], int start, int len)
157: throws SAXException {
158: this .stack.setOffset(this .oldOffset);
159: this .consumer.ignorableWhitespace(c, start, len);
160: this .stack.setOffset(this .newOffset);
161: }
162:
163: public void processingInstruction(String target, String data)
164: throws SAXException {
165: this .stack.setOffset(this .oldOffset);
166: this .consumer.processingInstruction(target, data);
167: this .stack.setOffset(this .newOffset);
168: }
169:
170: public void skippedEntity(String name) throws SAXException {
171: this .stack.setOffset(this .oldOffset);
172: this .consumer.skippedEntity(name);
173: this .stack.setOffset(this .newOffset);
174: }
175:
176: public void startDTD(String name, String publicId, String systemId)
177: throws SAXException {
178: this .stack.setOffset(this .oldOffset);
179: this .consumer.startDTD(name, publicId, systemId);
180: this .stack.setOffset(this .newOffset);
181: }
182:
183: public void endDTD() throws SAXException {
184: this .stack.setOffset(this .oldOffset);
185: this .consumer.endDTD();
186: this .stack.setOffset(this .newOffset);
187: }
188:
189: public void startEntity(String name) throws SAXException {
190: this .stack.setOffset(this .oldOffset);
191: this .consumer.startEntity(name);
192: this .stack.setOffset(this .newOffset);
193: }
194:
195: public void endEntity(String name) throws SAXException {
196: this .stack.setOffset(this .oldOffset);
197: this .consumer.endEntity(name);
198: this .stack.setOffset(this .newOffset);
199: }
200:
201: public void startCDATA() throws SAXException {
202: this .stack.setOffset(this .oldOffset);
203: this .consumer.startCDATA();
204: this .stack.setOffset(this .newOffset);
205: }
206:
207: public void endCDATA() throws SAXException {
208: this .stack.setOffset(this .oldOffset);
209: this .consumer.endCDATA();
210: this .stack.setOffset(this .newOffset);
211: }
212:
213: public void comment(char ch[], int start, int len)
214: throws SAXException {
215: this.stack.setOffset(this.oldOffset);
216: this.consumer.comment(ch, start, len);
217: this.stack.setOffset(this.newOffset);
218: }
219: }
|