From 65dfc5202d9fa7c5931c0b0be5cb38337eefe017 Mon Sep 17 00:00:00 2001 From: "Yuan.Wang" <1536296691@qq.com> Date: Tue, 23 May 2023 17:31:35 +0800 Subject: [PATCH 1/5] =?UTF-8?q?REPORT-95576=20spring=20framework=20?= =?UTF-8?q?=E9=AB=98=E5=8D=B1=E6=BC=8F=E6=B4=9E=EF=BC=8C=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../caucho/BurlapClientInterceptor.java | 194 ------- .../remoting/caucho/BurlapExporter.java | 97 ---- .../caucho/BurlapProxyFactoryBean.java | 73 --- .../caucho/BurlapServiceExporter.java | 76 --- .../caucho/HessianClientInterceptor.java | 297 ---------- .../remoting/caucho/HessianExporter.java | 247 --------- .../caucho/HessianProxyFactoryBean.java | 70 --- .../caucho/HessianServiceExporter.java | 73 --- .../caucho/SimpleBurlapServiceExporter.java | 79 --- .../caucho/SimpleHessianServiceExporter.java | 77 --- .../remoting/caucho/package-info.java | 10 - .../AbstractHttpInvokerRequestExecutor.java | 299 ---------- ...pComponentsHttpInvokerRequestExecutor.java | 418 -------------- .../HttpInvokerClientConfiguration.java | 42 -- .../HttpInvokerClientInterceptor.java | 233 -------- .../HttpInvokerProxyFactoryBean.java | 86 --- .../HttpInvokerRequestExecutor.java | 59 -- .../HttpInvokerServiceExporter.java | 225 -------- .../SimpleHttpInvokerRequestExecutor.java | 232 -------- .../SimpleHttpInvokerServiceExporter.java | 184 ------- .../remoting/httpinvoker/package-info.java | 11 - .../rmi/CodebaseAwareObjectInputStream.java | 119 ---- .../rmi/JndiRmiClientInterceptor.java | 510 ------------------ .../remoting/rmi/JndiRmiProxyFactoryBean.java | 102 ---- .../remoting/rmi/JndiRmiServiceExporter.java | 149 ----- .../RemoteInvocationSerializingExporter.java | 181 ------- .../remoting/rmi/RmiBasedExporter.java | 76 --- .../remoting/rmi/RmiClientInterceptor.java | 416 -------------- .../rmi/RmiClientInterceptorUtils.java | 193 ------- .../remoting/rmi/RmiInvocationHandler.java | 59 -- .../remoting/rmi/RmiInvocationWrapper.java | 77 --- .../remoting/rmi/RmiProxyFactoryBean.java | 91 ---- .../remoting/rmi/RmiRegistryFactoryBean.java | 314 ----------- .../remoting/rmi/RmiServiceExporter.java | 462 ---------------- .../remoting/rmi/package-info.java | 6 - 35 files changed, 5837 deletions(-) delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapClientInterceptor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapProxyFactoryBean.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianClientInterceptor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianProxyFactoryBean.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleBurlapServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleHessianServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/package-info.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/package-info.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiClientInterceptor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiBasedExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptor.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptorUtils.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationHandler.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationWrapper.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiProxyFactoryBean.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiRegistryFactoryBean.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiServiceExporter.java delete mode 100644 fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/package-info.java diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapClientInterceptor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapClientInterceptor.java deleted file mode 100644 index 1d5217375..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapClientInterceptor.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.UndeclaredThrowableException; -import java.net.ConnectException; -import java.net.MalformedURLException; - -import com.caucho.burlap.client.BurlapProxyFactory; -import com.caucho.burlap.client.BurlapRuntimeException; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import com.fr.third.springframework.remoting.RemoteAccessException; -import com.fr.third.springframework.remoting.RemoteConnectFailureException; -import com.fr.third.springframework.remoting.RemoteLookupFailureException; -import com.fr.third.springframework.remoting.RemoteProxyFailureException; -import com.fr.third.springframework.remoting.support.UrlBasedRemoteAccessor; -import com.fr.third.springframework.util.Assert; - -/** - * {@link org.aopalliance.intercept.MethodInterceptor} for accessing a Burlap service. - * Supports authentication via username and password. - * The service URL must be an HTTP URL exposing a Burlap service. - * - *

Burlap is a slim, XML-based RPC protocol. - * For information on Burlap, see the - * Burlap website - * - *

Note: There is no requirement for services accessed with this proxy factory - * to have been exported using Spring's {@link BurlapServiceExporter}, as there is - * no special handling involved. As a consequence, you can also access services that - * have been exported using Caucho's {@link com.caucho.burlap.server.BurlapServlet}. - * - * @author Juergen Hoeller - * @since 29.09.2003 - * @see #setServiceInterface - * @see #setServiceUrl - * @see #setUsername - * @see #setPassword - * @see BurlapServiceExporter - * @see BurlapProxyFactoryBean - * @see com.caucho.burlap.client.BurlapProxyFactory - * @see com.caucho.burlap.server.BurlapServlet - * @deprecated as of Spring 4.0, since Burlap hasn't evolved in years - * and is effectively retired (in contrast to its sibling Hessian) - */ -@Deprecated -public class BurlapClientInterceptor extends UrlBasedRemoteAccessor implements MethodInterceptor { - - private BurlapProxyFactory proxyFactory = new BurlapProxyFactory(); - - private Object burlapProxy; - - - /** - * Set the BurlapProxyFactory instance to use. - * If not specified, a default BurlapProxyFactory will be created. - *

Allows to use an externally configured factory instance, - * in particular a custom BurlapProxyFactory subclass. - */ - public void setProxyFactory(BurlapProxyFactory proxyFactory) { - this.proxyFactory = (proxyFactory != null ? proxyFactory : new BurlapProxyFactory()); - } - - /** - * Set the username that this factory should use to access the remote service. - * Default is none. - *

The username will be sent by Burlap via HTTP Basic Authentication. - * @see com.caucho.burlap.client.BurlapProxyFactory#setUser - */ - public void setUsername(String username) { - this.proxyFactory.setUser(username); - } - - /** - * Set the password that this factory should use to access the remote service. - * Default is none. - *

The password will be sent by Burlap via HTTP Basic Authentication. - * @see com.caucho.burlap.client.BurlapProxyFactory#setPassword - */ - public void setPassword(String password) { - this.proxyFactory.setPassword(password); - } - - /** - * Set whether overloaded methods should be enabled for remote invocations. - * Default is "false". - * @see com.caucho.burlap.client.BurlapProxyFactory#setOverloadEnabled - */ - public void setOverloadEnabled(boolean overloadEnabled) { - this.proxyFactory.setOverloadEnabled(overloadEnabled); - } - - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - prepare(); - } - - /** - * Initialize the Burlap proxy for this interceptor. - * @throws RemoteLookupFailureException if the service URL is invalid - */ - public void prepare() throws RemoteLookupFailureException { - try { - this.burlapProxy = createBurlapProxy(this.proxyFactory); - } - catch (MalformedURLException ex) { - throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex); - } - } - - /** - * Create the Burlap proxy that is wrapped by this interceptor. - * @param proxyFactory the proxy factory to use - * @return the Burlap proxy - * @throws MalformedURLException if thrown by the proxy factory - * @see com.caucho.burlap.client.BurlapProxyFactory#create - */ - protected Object createBurlapProxy(BurlapProxyFactory proxyFactory) throws MalformedURLException { - Assert.notNull(getServiceInterface(), "Property 'serviceInterface' is required"); - return proxyFactory.create(getServiceInterface(), getServiceUrl()); - } - - - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - if (this.burlapProxy == null) { - throw new IllegalStateException("BurlapClientInterceptor is not properly initialized - " + - "invoke 'prepare' before attempting any operations"); - } - - ClassLoader originalClassLoader = overrideThreadContextClassLoader(); - try { - return invocation.getMethod().invoke(this.burlapProxy, invocation.getArguments()); - } - catch (InvocationTargetException ex) { - Throwable targetEx = ex.getTargetException(); - if (targetEx instanceof BurlapRuntimeException) { - Throwable cause = targetEx.getCause(); - throw convertBurlapAccessException(cause != null ? cause : targetEx); - } - else if (targetEx instanceof UndeclaredThrowableException) { - UndeclaredThrowableException utex = (UndeclaredThrowableException) targetEx; - throw convertBurlapAccessException(utex.getUndeclaredThrowable()); - } - else { - throw targetEx; - } - } - catch (Throwable ex) { - throw new RemoteProxyFailureException( - "Failed to invoke Burlap proxy for remote service [" + getServiceUrl() + "]", ex); - } - finally { - resetThreadContextClassLoader(originalClassLoader); - } - } - - /** - * Convert the given Burlap access exception to an appropriate - * Spring RemoteAccessException. - * @param ex the exception to convert - * @return the RemoteAccessException to throw - */ - protected RemoteAccessException convertBurlapAccessException(Throwable ex) { - if (ex instanceof ConnectException) { - return new RemoteConnectFailureException( - "Cannot connect to Burlap remote service at [" + getServiceUrl() + "]", ex); - } - else { - return new RemoteAccessException( - "Cannot access Burlap remote service at [" + getServiceUrl() + "]", ex); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapExporter.java deleted file mode 100644 index 8f660633f..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapExporter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import com.caucho.burlap.io.BurlapInput; -import com.caucho.burlap.io.BurlapOutput; -import com.caucho.burlap.server.BurlapSkeleton; - -import com.fr.third.springframework.beans.factory.InitializingBean; -import com.fr.third.springframework.remoting.support.RemoteExporter; -import com.fr.third.springframework.util.Assert; - -/** - * General stream-based protocol exporter for a Burlap endpoint. - * - *

Burlap is a slim, XML-based RPC protocol. - * For information on Burlap, see the - * Burlap website. - * This exporter requires Burlap 3.x. - * - * @author Juergen Hoeller - * @since 2.5.1 - * @see #invoke(java.io.InputStream, java.io.OutputStream) - * @see BurlapServiceExporter - * @see SimpleBurlapServiceExporter - * @deprecated as of Spring 4.0, since Burlap hasn't evolved in years - * and is effectively retired (in contrast to its sibling Hessian) - */ -@Deprecated -public class BurlapExporter extends RemoteExporter implements InitializingBean { - - private BurlapSkeleton skeleton; - - - @Override - public void afterPropertiesSet() { - prepare(); - } - - /** - * Initialize this service exporter. - */ - public void prepare() { - checkService(); - checkServiceInterface(); - this.skeleton = new BurlapSkeleton(getProxyForService(), getServiceInterface()); - } - - - /** - * Perform an invocation on the exported object. - * @param inputStream the request stream - * @param outputStream the response stream - * @throws Throwable if invocation failed - */ - public void invoke(InputStream inputStream, OutputStream outputStream) throws Throwable { - Assert.notNull(this.skeleton, "Burlap exporter has not been initialized"); - ClassLoader originalClassLoader = overrideThreadContextClassLoader(); - try { - this.skeleton.invoke(new BurlapInput(inputStream), new BurlapOutput(outputStream)); - } - finally { - try { - inputStream.close(); - } - catch (IOException ex) { - // ignore - } - try { - outputStream.close(); - } - catch (IOException ex) { - // ignore - } - resetThreadContextClassLoader(originalClassLoader); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapProxyFactoryBean.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapProxyFactoryBean.java deleted file mode 100644 index 719641633..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapProxyFactoryBean.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import com.fr.third.springframework.aop.framework.ProxyFactory; -import com.fr.third.springframework.beans.factory.FactoryBean; - -/** - * {@link FactoryBean} for Burlap proxies. Exposes the proxied service - * for use as a bean reference, using the specified service interface. - * - *

Burlap is a slim, XML-based RPC protocol. - * For information on Burlap, see the - * Burlap website - * - *

The service URL must be an HTTP URL exposing a Burlap service. - * For details, see the {@link BurlapClientInterceptor} javadoc. - * - * @author Juergen Hoeller - * @since 13.05.2003 - * @see #setServiceInterface - * @see #setServiceUrl - * @see BurlapClientInterceptor - * @see BurlapServiceExporter - * @see com.fr.third.springframework.remoting.caucho.HessianProxyFactoryBean - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean - * @see com.fr.third.springframework.remoting.rmi.RmiProxyFactoryBean - * @deprecated as of Spring 4.0, since Burlap hasn't evolved in years - * and is effectively retired (in contrast to its sibling Hessian) - */ -@Deprecated -public class BurlapProxyFactoryBean extends BurlapClientInterceptor implements FactoryBean { - - private Object serviceProxy; - - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader()); - } - - - @Override - public Object getObject() { - return this.serviceProxy; - } - - @Override - public Class getObjectType() { - return getServiceInterface(); - } - - @Override - public boolean isSingleton() { - return true; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapServiceExporter.java deleted file mode 100644 index a730c2bf7..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/BurlapServiceExporter.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.fr.third.springframework.web.HttpRequestHandler; -import com.fr.third.springframework.web.HttpRequestMethodNotSupportedException; -import com.fr.third.springframework.web.util.NestedServletException; - -/** - * Servlet-API-based HTTP request handler that exports the specified service bean - * as Burlap service endpoint, accessible via a Burlap proxy. - * - *

Note: Spring also provides an alternative version of this exporter, - * for Sun's JRE 1.6 HTTP server: {@link SimpleBurlapServiceExporter}. - * - *

Burlap is a slim, XML-based RPC protocol. - * For information on Burlap, see the - * Burlap website. - * This exporter requires Burlap 3.x. - * - *

Note: Burlap services exported with this class can be accessed by - * any Burlap client, as there isn't any special handling involved. - * - * @author Juergen Hoeller - * @since 13.05.2003 - * @see BurlapClientInterceptor - * @see BurlapProxyFactoryBean - * @see com.fr.third.springframework.remoting.caucho.HessianServiceExporter - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerServiceExporter - * @see com.fr.third.springframework.remoting.rmi.RmiServiceExporter - * @deprecated as of Spring 4.0, since Burlap hasn't evolved in years - * and is effectively retired (in contrast to its sibling Hessian) - */ -@Deprecated -public class BurlapServiceExporter extends BurlapExporter implements HttpRequestHandler { - - /** - * Processes the incoming Burlap request and creates a Burlap response. - */ - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - if (!"POST".equals(request.getMethod())) { - throw new HttpRequestMethodNotSupportedException(request.getMethod(), - new String[] {"POST"}, "BurlapServiceExporter only supports POST requests"); - } - - try { - invoke(request.getInputStream(), response.getOutputStream()); - } - catch (Throwable ex) { - throw new NestedServletException("Burlap skeleton invocation failed", ex); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianClientInterceptor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianClientInterceptor.java deleted file mode 100644 index ea1526753..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianClientInterceptor.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.UndeclaredThrowableException; -import java.net.ConnectException; -import java.net.MalformedURLException; - -import com.caucho.hessian.HessianException; -import com.caucho.hessian.client.HessianConnectionException; -import com.caucho.hessian.client.HessianConnectionFactory; -import com.caucho.hessian.client.HessianProxyFactory; -import com.caucho.hessian.client.HessianRuntimeException; -import com.caucho.hessian.io.SerializerFactory; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import com.fr.third.springframework.remoting.RemoteAccessException; -import com.fr.third.springframework.remoting.RemoteConnectFailureException; -import com.fr.third.springframework.remoting.RemoteLookupFailureException; -import com.fr.third.springframework.remoting.RemoteProxyFailureException; -import com.fr.third.springframework.remoting.support.UrlBasedRemoteAccessor; -import com.fr.third.springframework.util.Assert; - -/** - * {@link org.aopalliance.intercept.MethodInterceptor} for accessing a Hessian service. - * Supports authentication via username and password. - * The service URL must be an HTTP URL exposing a Hessian service. - * - *

Hessian is a slim, binary RPC protocol. - * For information on Hessian, see the - * Hessian website - * Note: As of Spring 4.0, this client requires Hessian 4.0 or above. - * - *

Note: There is no requirement for services accessed with this proxy factory - * to have been exported using Spring's {@link HessianServiceExporter}, as there is - * no special handling involved. As a consequence, you can also access services that - * have been exported using Caucho's {@link com.caucho.hessian.server.HessianServlet}. - * - * @author Juergen Hoeller - * @since 29.09.2003 - * @see #setServiceInterface - * @see #setServiceUrl - * @see #setUsername - * @see #setPassword - * @see HessianServiceExporter - * @see HessianProxyFactoryBean - * @see com.caucho.hessian.client.HessianProxyFactory - * @see com.caucho.hessian.server.HessianServlet - */ -public class HessianClientInterceptor extends UrlBasedRemoteAccessor implements MethodInterceptor { - - private HessianProxyFactory proxyFactory = new HessianProxyFactory(); - - private Object hessianProxy; - - - /** - * Set the HessianProxyFactory instance to use. - * If not specified, a default HessianProxyFactory will be created. - *

Allows to use an externally configured factory instance, - * in particular a custom HessianProxyFactory subclass. - */ - public void setProxyFactory(HessianProxyFactory proxyFactory) { - this.proxyFactory = (proxyFactory != null ? proxyFactory : new HessianProxyFactory()); - } - - /** - * Specify the Hessian SerializerFactory to use. - *

This will typically be passed in as an inner bean definition - * of type {@code com.caucho.hessian.io.SerializerFactory}, - * with custom bean property values applied. - */ - public void setSerializerFactory(SerializerFactory serializerFactory) { - this.proxyFactory.setSerializerFactory(serializerFactory); - } - - /** - * Set whether to send the Java collection type for each serialized - * collection. Default is "true". - */ - public void setSendCollectionType(boolean sendCollectionType) { - this.proxyFactory.getSerializerFactory().setSendCollectionType(sendCollectionType); - } - - /** - * Set whether to allow non-serializable types as Hessian arguments - * and return values. Default is "true". - */ - public void setAllowNonSerializable(boolean allowNonSerializable) { - this.proxyFactory.getSerializerFactory().setAllowNonSerializable(allowNonSerializable); - } - - /** - * Set whether overloaded methods should be enabled for remote invocations. - * Default is "false". - * @see com.caucho.hessian.client.HessianProxyFactory#setOverloadEnabled - */ - public void setOverloadEnabled(boolean overloadEnabled) { - this.proxyFactory.setOverloadEnabled(overloadEnabled); - } - - /** - * Set the username that this factory should use to access the remote service. - * Default is none. - *

The username will be sent by Hessian via HTTP Basic Authentication. - * @see com.caucho.hessian.client.HessianProxyFactory#setUser - */ - public void setUsername(String username) { - this.proxyFactory.setUser(username); - } - - /** - * Set the password that this factory should use to access the remote service. - * Default is none. - *

The password will be sent by Hessian via HTTP Basic Authentication. - * @see com.caucho.hessian.client.HessianProxyFactory#setPassword - */ - public void setPassword(String password) { - this.proxyFactory.setPassword(password); - } - - /** - * Set whether Hessian's debug mode should be enabled. - * Default is "false". - * @see com.caucho.hessian.client.HessianProxyFactory#setDebug - */ - public void setDebug(boolean debug) { - this.proxyFactory.setDebug(debug); - } - - /** - * Set whether to use a chunked post for sending a Hessian request. - * @see com.caucho.hessian.client.HessianProxyFactory#setChunkedPost - */ - public void setChunkedPost(boolean chunkedPost) { - this.proxyFactory.setChunkedPost(chunkedPost); - } - - /** - * Specify a custom HessianConnectionFactory to use for the Hessian client. - */ - public void setConnectionFactory(HessianConnectionFactory connectionFactory) { - this.proxyFactory.setConnectionFactory(connectionFactory); - } - - /** - * Set the socket connect timeout to use for the Hessian client. - * @see com.caucho.hessian.client.HessianProxyFactory#setConnectTimeout - */ - public void setConnectTimeout(long timeout) { - this.proxyFactory.setConnectTimeout(timeout); - } - - /** - * Set the timeout to use when waiting for a reply from the Hessian service. - * @see com.caucho.hessian.client.HessianProxyFactory#setReadTimeout - */ - public void setReadTimeout(long timeout) { - this.proxyFactory.setReadTimeout(timeout); - } - - /** - * Set whether version 2 of the Hessian protocol should be used for - * parsing requests and replies. Default is "false". - * @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Request - */ - public void setHessian2(boolean hessian2) { - this.proxyFactory.setHessian2Request(hessian2); - this.proxyFactory.setHessian2Reply(hessian2); - } - - /** - * Set whether version 2 of the Hessian protocol should be used for - * parsing requests. Default is "false". - * @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Request - */ - public void setHessian2Request(boolean hessian2) { - this.proxyFactory.setHessian2Request(hessian2); - } - - /** - * Set whether version 2 of the Hessian protocol should be used for - * parsing replies. Default is "false". - * @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Reply - */ - public void setHessian2Reply(boolean hessian2) { - this.proxyFactory.setHessian2Reply(hessian2); - } - - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - prepare(); - } - - /** - * Initialize the Hessian proxy for this interceptor. - * @throws RemoteLookupFailureException if the service URL is invalid - */ - public void prepare() throws RemoteLookupFailureException { - try { - this.hessianProxy = createHessianProxy(this.proxyFactory); - } - catch (MalformedURLException ex) { - throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex); - } - } - - /** - * Create the Hessian proxy that is wrapped by this interceptor. - * @param proxyFactory the proxy factory to use - * @return the Hessian proxy - * @throws MalformedURLException if thrown by the proxy factory - * @see com.caucho.hessian.client.HessianProxyFactory#create - */ - protected Object createHessianProxy(HessianProxyFactory proxyFactory) throws MalformedURLException { - Assert.notNull(getServiceInterface(), "'serviceInterface' is required"); - return proxyFactory.create(getServiceInterface(), getServiceUrl(), getBeanClassLoader()); - } - - - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - if (this.hessianProxy == null) { - throw new IllegalStateException("HessianClientInterceptor is not properly initialized - " + - "invoke 'prepare' before attempting any operations"); - } - - ClassLoader originalClassLoader = overrideThreadContextClassLoader(); - try { - return invocation.getMethod().invoke(this.hessianProxy, invocation.getArguments()); - } - catch (InvocationTargetException ex) { - Throwable targetEx = ex.getTargetException(); - // Hessian 4.0 check: another layer of InvocationTargetException. - if (targetEx instanceof InvocationTargetException) { - targetEx = ((InvocationTargetException) targetEx).getTargetException(); - } - if (targetEx instanceof HessianConnectionException) { - throw convertHessianAccessException(targetEx); - } - else if (targetEx instanceof HessianException || targetEx instanceof HessianRuntimeException) { - Throwable cause = targetEx.getCause(); - throw convertHessianAccessException(cause != null ? cause : targetEx); - } - else if (targetEx instanceof UndeclaredThrowableException) { - UndeclaredThrowableException utex = (UndeclaredThrowableException) targetEx; - throw convertHessianAccessException(utex.getUndeclaredThrowable()); - } - else { - throw targetEx; - } - } - catch (Throwable ex) { - throw new RemoteProxyFailureException( - "Failed to invoke Hessian proxy for remote service [" + getServiceUrl() + "]", ex); - } - finally { - resetThreadContextClassLoader(originalClassLoader); - } - } - - /** - * Convert the given Hessian access exception to an appropriate - * Spring RemoteAccessException. - * @param ex the exception to convert - * @return the RemoteAccessException to throw - */ - protected RemoteAccessException convertHessianAccessException(Throwable ex) { - if (ex instanceof HessianConnectionException || ex instanceof ConnectException) { - return new RemoteConnectFailureException( - "Cannot connect to Hessian remote service at [" + getServiceUrl() + "]", ex); - } - else { - return new RemoteAccessException( - "Cannot access Hessian remote service at [" + getServiceUrl() + "]", ex); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianExporter.java deleted file mode 100644 index 4bfbd3a9c..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianExporter.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; - -import com.caucho.hessian.io.AbstractHessianInput; -import com.caucho.hessian.io.AbstractHessianOutput; -import com.caucho.hessian.io.Hessian2Input; -import com.caucho.hessian.io.Hessian2Output; -import com.caucho.hessian.io.HessianDebugInputStream; -import com.caucho.hessian.io.HessianDebugOutputStream; -import com.caucho.hessian.io.HessianInput; -import com.caucho.hessian.io.HessianOutput; -import com.caucho.hessian.io.HessianRemoteResolver; -import com.caucho.hessian.io.SerializerFactory; -import com.caucho.hessian.server.HessianSkeleton; -import org.apache.commons.logging.Log; - -import com.fr.third.springframework.beans.factory.InitializingBean; -import com.fr.third.springframework.remoting.support.RemoteExporter; -import com.fr.third.springframework.util.Assert; -import com.fr.third.springframework.util.CommonsLogWriter; - -/** - * General stream-based protocol exporter for a Hessian endpoint. - * - *

Hessian is a slim, binary RPC protocol. - * For information on Hessian, see the - * Hessian website. - * Note: As of Spring 4.0, this exporter requires Hessian 4.0 or above. - * - * @author Juergen Hoeller - * @since 2.5.1 - * @see #invoke(java.io.InputStream, java.io.OutputStream) - * @see HessianServiceExporter - * @see SimpleHessianServiceExporter - */ -public class HessianExporter extends RemoteExporter implements InitializingBean { - - public static final String CONTENT_TYPE_HESSIAN = "application/x-hessian"; - - - private SerializerFactory serializerFactory = new SerializerFactory(); - - private HessianRemoteResolver remoteResolver; - - private Log debugLogger; - - private HessianSkeleton skeleton; - - - /** - * Specify the Hessian SerializerFactory to use. - *

This will typically be passed in as an inner bean definition - * of type {@code com.caucho.hessian.io.SerializerFactory}, - * with custom bean property values applied. - */ - public void setSerializerFactory(SerializerFactory serializerFactory) { - this.serializerFactory = (serializerFactory != null ? serializerFactory : new SerializerFactory()); - } - - /** - * Set whether to send the Java collection type for each serialized - * collection. Default is "true". - */ - public void setSendCollectionType(boolean sendCollectionType) { - this.serializerFactory.setSendCollectionType(sendCollectionType); - } - - /** - * Set whether to allow non-serializable types as Hessian arguments - * and return values. Default is "true". - */ - public void setAllowNonSerializable(boolean allowNonSerializable) { - this.serializerFactory.setAllowNonSerializable(allowNonSerializable); - } - - /** - * Specify a custom HessianRemoteResolver to use for resolving remote - * object references. - */ - public void setRemoteResolver(HessianRemoteResolver remoteResolver) { - this.remoteResolver = remoteResolver; - } - - /** - * Set whether Hessian's debug mode should be enabled, logging to - * this exporter's Commons Logging log. Default is "false". - * @see com.caucho.hessian.client.HessianProxyFactory#setDebug - */ - public void setDebug(boolean debug) { - this.debugLogger = (debug ? logger : null); - } - - - @Override - public void afterPropertiesSet() { - prepare(); - } - - /** - * Initialize this exporter. - */ - public void prepare() { - checkService(); - checkServiceInterface(); - this.skeleton = new HessianSkeleton(getProxyForService(), getServiceInterface()); - } - - - /** - * Perform an invocation on the exported object. - * @param inputStream the request stream - * @param outputStream the response stream - * @throws Throwable if invocation failed - */ - public void invoke(InputStream inputStream, OutputStream outputStream) throws Throwable { - Assert.notNull(this.skeleton, "Hessian exporter has not been initialized"); - doInvoke(this.skeleton, inputStream, outputStream); - } - - /** - * Actually invoke the skeleton with the given streams. - * @param skeleton the skeleton to invoke - * @param inputStream the request stream - * @param outputStream the response stream - * @throws Throwable if invocation failed - */ - protected void doInvoke(HessianSkeleton skeleton, InputStream inputStream, OutputStream outputStream) - throws Throwable { - - ClassLoader originalClassLoader = overrideThreadContextClassLoader(); - try { - InputStream isToUse = inputStream; - OutputStream osToUse = outputStream; - - if (this.debugLogger != null && this.debugLogger.isDebugEnabled()) { - PrintWriter debugWriter = new PrintWriter(new CommonsLogWriter(this.debugLogger)); - @SuppressWarnings("resource") - HessianDebugInputStream dis = new HessianDebugInputStream(inputStream, debugWriter); - @SuppressWarnings("resource") - HessianDebugOutputStream dos = new HessianDebugOutputStream(outputStream, debugWriter); - dis.startTop2(); - dos.startTop2(); - isToUse = dis; - osToUse = dos; - } - - if (!isToUse.markSupported()) { - isToUse = new BufferedInputStream(isToUse); - isToUse.mark(1); - } - - int code = isToUse.read(); - int major; - int minor; - - AbstractHessianInput in; - AbstractHessianOutput out; - - if (code == 'H') { - // Hessian 2.0 stream - major = isToUse.read(); - minor = isToUse.read(); - if (major != 0x02) { - throw new IOException("Version " + major + '.' + minor + " is not understood"); - } - in = new Hessian2Input(isToUse); - out = new Hessian2Output(osToUse); - in.readCall(); - } - else if (code == 'C') { - // Hessian 2.0 call... for some reason not handled in HessianServlet! - isToUse.reset(); - in = new Hessian2Input(isToUse); - out = new Hessian2Output(osToUse); - in.readCall(); - } - else if (code == 'c') { - // Hessian 1.0 call - major = isToUse.read(); - minor = isToUse.read(); - in = new HessianInput(isToUse); - if (major >= 2) { - out = new Hessian2Output(osToUse); - } - else { - out = new HessianOutput(osToUse); - } - } - else { - throw new IOException("Expected 'H'/'C' (Hessian 2.0) or 'c' (Hessian 1.0) in hessian input at " + code); - } - - if (this.serializerFactory != null) { - in.setSerializerFactory(this.serializerFactory); - out.setSerializerFactory(this.serializerFactory); - } - if (this.remoteResolver != null) { - in.setRemoteResolver(this.remoteResolver); - } - - try { - skeleton.invoke(in, out); - } - finally { - try { - in.close(); - isToUse.close(); - } - catch (IOException ex) { - // ignore - } - try { - out.close(); - osToUse.close(); - } - catch (IOException ex) { - // ignore - } - } - } - finally { - resetThreadContextClassLoader(originalClassLoader); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianProxyFactoryBean.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianProxyFactoryBean.java deleted file mode 100644 index dcc1edba7..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianProxyFactoryBean.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import com.fr.third.springframework.aop.framework.ProxyFactory; -import com.fr.third.springframework.beans.factory.FactoryBean; - -/** - * {@link FactoryBean} for Hessian proxies. Exposes the proxied service - * for use as a bean reference, using the specified service interface. - * - *

Hessian is a slim, binary RPC protocol. - * For information on Hessian, see the - * Hessian website - * Note: As of Spring 4.0, this proxy factory requires Hessian 4.0 or above. - * - *

The service URL must be an HTTP URL exposing a Hessian service. - * For details, see the {@link HessianClientInterceptor} javadoc. - * - * @author Juergen Hoeller - * @since 13.05.2003 - * @see #setServiceInterface - * @see #setServiceUrl - * @see HessianClientInterceptor - * @see HessianServiceExporter - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean - * @see com.fr.third.springframework.remoting.rmi.RmiProxyFactoryBean - */ -public class HessianProxyFactoryBean extends HessianClientInterceptor implements FactoryBean { - - private Object serviceProxy; - - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader()); - } - - - @Override - public Object getObject() { - return this.serviceProxy; - } - - @Override - public Class getObjectType() { - return getServiceInterface(); - } - - @Override - public boolean isSingleton() { - return true; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianServiceExporter.java deleted file mode 100644 index 9e2f487fb..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/HessianServiceExporter.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.fr.third.springframework.web.HttpRequestHandler; -import com.fr.third.springframework.web.HttpRequestMethodNotSupportedException; -import com.fr.third.springframework.web.util.NestedServletException; - -/** - * Servlet-API-based HTTP request handler that exports the specified service bean - * as Hessian service endpoint, accessible via a Hessian proxy. - * - *

Note: Spring also provides an alternative version of this exporter, - * for Sun's JRE 1.6 HTTP server: {@link SimpleHessianServiceExporter}. - * - *

Hessian is a slim, binary RPC protocol. - * For information on Hessian, see the - * Hessian website. - * Note: As of Spring 4.0, this exporter requires Hessian 4.0 or above. - * - *

Hessian services exported with this class can be accessed by - * any Hessian client, as there isn't any special handling involved. - * - * @author Juergen Hoeller - * @since 13.05.2003 - * @see HessianClientInterceptor - * @see HessianProxyFactoryBean - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerServiceExporter - * @see com.fr.third.springframework.remoting.rmi.RmiServiceExporter - */ -public class HessianServiceExporter extends HessianExporter implements HttpRequestHandler { - - /** - * Processes the incoming Hessian request and creates a Hessian response. - */ - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - if (!"POST".equals(request.getMethod())) { - throw new HttpRequestMethodNotSupportedException(request.getMethod(), - new String[] {"POST"}, "HessianServiceExporter only supports POST requests"); - } - - response.setContentType(CONTENT_TYPE_HESSIAN); - try { - invoke(request.getInputStream(), response.getOutputStream()); - } - catch (Throwable ex) { - throw new NestedServletException("Hessian skeleton invocation failed", ex); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleBurlapServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleBurlapServiceExporter.java deleted file mode 100644 index aad921eae..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleBurlapServiceExporter.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2002-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - -import com.fr.third.springframework.lang.UsesSunHttpServer; -import com.fr.third.springframework.util.FileCopyUtils; - -/** - * HTTP request handler that exports the specified service bean as - * Burlap service endpoint, accessible via a Burlap proxy. - * Designed for Sun's JRE 1.6 HTTP server, implementing the - * {@link com.sun.net.httpserver.HttpHandler} interface. - * - *

Burlap is a slim, XML-based RPC protocol. - * For information on Burlap, see the - * Burlap website. - * This exporter requires Burlap 3.x. - * - *

Note: Burlap services exported with this class can be accessed by - * any Burlap client, as there isn't any special handling involved. - * - * @author Juergen Hoeller - * @since 2.5.1 - * @see com.fr.third.springframework.remoting.caucho.BurlapClientInterceptor - * @see com.fr.third.springframework.remoting.caucho.BurlapProxyFactoryBean - * @see SimpleHessianServiceExporter - * @see com.fr.third.springframework.remoting.httpinvoker.SimpleHttpInvokerServiceExporter - * @deprecated as of Spring 4.0, since Burlap hasn't evolved in years - * and is effectively retired (in contrast to its sibling Hessian) - */ -@Deprecated -@UsesSunHttpServer -public class SimpleBurlapServiceExporter extends BurlapExporter implements HttpHandler { - - /** - * Processes the incoming Burlap request and creates a Burlap response. - */ - @Override - public void handle(HttpExchange exchange) throws IOException { - if (!"POST".equals(exchange.getRequestMethod())) { - exchange.getResponseHeaders().set("Allow", "POST"); - exchange.sendResponseHeaders(405, -1); - return; - } - - ByteArrayOutputStream output = new ByteArrayOutputStream(1024); - try { - invoke(exchange.getRequestBody(), output); - } - catch (Throwable ex) { - exchange.sendResponseHeaders(500, -1); - logger.error("Burlap skeleton invocation failed", ex); - } - - exchange.sendResponseHeaders(200, output.size()); - FileCopyUtils.copy(output.toByteArray(), exchange.getResponseBody()); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleHessianServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleHessianServiceExporter.java deleted file mode 100644 index 8d42da992..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/SimpleHessianServiceExporter.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2002-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.caucho; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - -import com.fr.third.springframework.lang.UsesSunHttpServer; -import com.fr.third.springframework.util.FileCopyUtils; - -/** - * HTTP request handler that exports the specified service bean as - * Hessian service endpoint, accessible via a Hessian proxy. - * Designed for Sun's JRE 1.6 HTTP server, implementing the - * {@link com.sun.net.httpserver.HttpHandler} interface. - * - *

Hessian is a slim, binary RPC protocol. - * For information on Hessian, see the - * Hessian website. - * Note: As of Spring 4.0, this exporter requires Hessian 4.0 or above. - * - *

Hessian services exported with this class can be accessed by - * any Hessian client, as there isn't any special handling involved. - * - * @author Juergen Hoeller - * @since 2.5.1 - * @see com.fr.third.springframework.remoting.caucho.HessianClientInterceptor - * @see com.fr.third.springframework.remoting.caucho.HessianProxyFactoryBean - * @see com.fr.third.springframework.remoting.httpinvoker.SimpleHttpInvokerServiceExporter - */ -@UsesSunHttpServer -public class SimpleHessianServiceExporter extends HessianExporter implements HttpHandler { - - /** - * Processes the incoming Hessian request and creates a Hessian response. - */ - @Override - public void handle(HttpExchange exchange) throws IOException { - if (!"POST".equals(exchange.getRequestMethod())) { - exchange.getResponseHeaders().set("Allow", "POST"); - exchange.sendResponseHeaders(405, -1); - return; - } - - ByteArrayOutputStream output = new ByteArrayOutputStream(1024); - try { - invoke(exchange.getRequestBody(), output); - } - catch (Throwable ex) { - exchange.sendResponseHeaders(500, -1); - logger.error("Hessian skeleton invocation failed", ex); - return; - } - - exchange.getResponseHeaders().set("Content-Type", CONTENT_TYPE_HESSIAN); - exchange.sendResponseHeaders(200, output.size()); - FileCopyUtils.copy(output.toByteArray(), exchange.getResponseBody()); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/package-info.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/package-info.java deleted file mode 100644 index 081376924..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/caucho/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/** - * This package provides remoting classes for Caucho's Hessian protocol: - * a proxy factory for accessing Hessian services, and an exporter for - * making beans available to Hessian clients. - * - *

Hessian is a slim, binary RPC protocol over HTTP. - * For information on Hessian, see the - * Hessian website - */ -package com.fr.third.springframework.remoting.caucho; diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java deleted file mode 100644 index f0c9aadc2..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.rmi.RemoteException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.fr.third.springframework.beans.factory.BeanClassLoaderAware; -import com.fr.third.springframework.remoting.rmi.CodebaseAwareObjectInputStream; -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; -import com.fr.third.springframework.util.Assert; -import com.fr.third.springframework.util.ClassUtils; - -/** - * Abstract base implementation of the HttpInvokerRequestExecutor interface. - * - *

Pre-implements serialization of RemoteInvocation objects and - * deserialization of RemoteInvocationResults objects. - * - * @author Juergen Hoeller - * @since 1.1 - * @see #doExecuteRequest - */ -public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerRequestExecutor, BeanClassLoaderAware { - - /** - * Default content type: "application/x-java-serialized-object" - */ - public static final String CONTENT_TYPE_SERIALIZED_OBJECT = "application/x-java-serialized-object"; - - private static final int SERIALIZED_INVOCATION_BYTE_ARRAY_INITIAL_SIZE = 1024; - - - protected static final String HTTP_METHOD_POST = "POST"; - - protected static final String HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language"; - - protected static final String HTTP_HEADER_ACCEPT_ENCODING = "Accept-Encoding"; - - protected static final String HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding"; - - protected static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type"; - - protected static final String HTTP_HEADER_CONTENT_LENGTH = "Content-Length"; - - protected static final String ENCODING_GZIP = "gzip"; - - - protected final Log logger = LogFactory.getLog(getClass()); - - private String contentType = CONTENT_TYPE_SERIALIZED_OBJECT; - - private boolean acceptGzipEncoding = true; - - private ClassLoader beanClassLoader; - - - /** - * Specify the content type to use for sending HTTP invoker requests. - *

Default is "application/x-java-serialized-object". - */ - public void setContentType(String contentType) { - Assert.notNull(contentType, "'contentType' must not be null"); - this.contentType = contentType; - } - - /** - * Return the content type to use for sending HTTP invoker requests. - */ - public String getContentType() { - return this.contentType; - } - - /** - * Set whether to accept GZIP encoding, that is, whether to - * send the HTTP "Accept-Encoding" header with "gzip" as value. - *

Default is "true". Turn this flag off if you do not want - * GZIP response compression even if enabled on the HTTP server. - */ - public void setAcceptGzipEncoding(boolean acceptGzipEncoding) { - this.acceptGzipEncoding = acceptGzipEncoding; - } - - /** - * Return whether to accept GZIP encoding, that is, whether to - * send the HTTP "Accept-Encoding" header with "gzip" as value. - */ - public boolean isAcceptGzipEncoding() { - return this.acceptGzipEncoding; - } - - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.beanClassLoader = classLoader; - } - - /** - * Return the bean ClassLoader that this executor is supposed to use. - */ - protected ClassLoader getBeanClassLoader() { - return this.beanClassLoader; - } - - - @Override - public final RemoteInvocationResult executeRequest( - HttpInvokerClientConfiguration config, RemoteInvocation invocation) throws Exception { - - ByteArrayOutputStream baos = getByteArrayOutputStream(invocation); - if (logger.isDebugEnabled()) { - logger.debug("Sending HTTP invoker request for service at [" + config.getServiceUrl() + - "], with size " + baos.size()); - } - return doExecuteRequest(config, baos); - } - - /** - * Serialize the given RemoteInvocation into a ByteArrayOutputStream. - * @param invocation the RemoteInvocation object - * @return a ByteArrayOutputStream with the serialized RemoteInvocation - * @throws IOException if thrown by I/O methods - */ - protected ByteArrayOutputStream getByteArrayOutputStream(RemoteInvocation invocation) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(SERIALIZED_INVOCATION_BYTE_ARRAY_INITIAL_SIZE); - writeRemoteInvocation(invocation, baos); - return baos; - } - - /** - * Serialize the given RemoteInvocation to the given OutputStream. - *

The default implementation gives {@code decorateOutputStream} a chance - * to decorate the stream first (for example, for custom encryption or compression). - * Creates an {@code ObjectOutputStream} for the final stream and calls - * {@code doWriteRemoteInvocation} to actually write the object. - *

Can be overridden for custom serialization of the invocation. - * @param invocation the RemoteInvocation object - * @param os the OutputStream to write to - * @throws IOException if thrown by I/O methods - * @see #decorateOutputStream - * @see #doWriteRemoteInvocation - */ - protected void writeRemoteInvocation(RemoteInvocation invocation, OutputStream os) throws IOException { - ObjectOutputStream oos = new ObjectOutputStream(decorateOutputStream(os)); - try { - doWriteRemoteInvocation(invocation, oos); - } - finally { - oos.close(); - } - } - - /** - * Return the OutputStream to use for writing remote invocations, - * potentially decorating the given original OutputStream. - *

The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param os the original OutputStream - * @return the potentially decorated OutputStream - */ - protected OutputStream decorateOutputStream(OutputStream os) throws IOException { - return os; - } - - /** - * Perform the actual writing of the given invocation object to the - * given ObjectOutputStream. - *

The default implementation simply calls {@code writeObject}. - * Can be overridden for serialization of a custom wrapper object rather - * than the plain invocation, for example an encryption-aware holder. - * @param invocation the RemoteInvocation object - * @param oos the ObjectOutputStream to write to - * @throws IOException if thrown by I/O methods - * @see java.io.ObjectOutputStream#writeObject - */ - protected void doWriteRemoteInvocation(RemoteInvocation invocation, ObjectOutputStream oos) throws IOException { - oos.writeObject(invocation); - } - - - /** - * Execute a request to send the given serialized remote invocation. - *

Implementations will usually call {@code readRemoteInvocationResult} - * to deserialize a returned RemoteInvocationResult object. - * @param config the HTTP invoker configuration that specifies the - * target service - * @param baos the ByteArrayOutputStream that contains the serialized - * RemoteInvocation object - * @return the RemoteInvocationResult object - * @throws IOException if thrown by I/O operations - * @throws ClassNotFoundException if thrown during deserialization - * @throws Exception in case of general errors - * @see #readRemoteInvocationResult(java.io.InputStream, String) - */ - protected abstract RemoteInvocationResult doExecuteRequest( - HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) - throws Exception; - - /** - * Deserialize a RemoteInvocationResult object from the given InputStream. - *

Gives {@code decorateInputStream} a chance to decorate the stream - * first (for example, for custom encryption or compression). Creates an - * {@code ObjectInputStream} via {@code createObjectInputStream} and - * calls {@code doReadRemoteInvocationResult} to actually read the object. - *

Can be overridden for custom serialization of the invocation. - * @param is the InputStream to read from - * @param codebaseUrl the codebase URL to load classes from if not found locally - * @return the RemoteInvocationResult object - * @throws IOException if thrown by I/O methods - * @throws ClassNotFoundException if thrown during deserialization - * @see #decorateInputStream - * @see #createObjectInputStream - * @see #doReadRemoteInvocationResult - */ - protected RemoteInvocationResult readRemoteInvocationResult(InputStream is, String codebaseUrl) - throws IOException, ClassNotFoundException { - - ObjectInputStream ois = createObjectInputStream(decorateInputStream(is), codebaseUrl); - try { - return doReadRemoteInvocationResult(ois); - } - finally { - ois.close(); - } - } - - /** - * Return the InputStream to use for reading remote invocation results, - * potentially decorating the given original InputStream. - *

The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param is the original InputStream - * @return the potentially decorated InputStream - */ - protected InputStream decorateInputStream(InputStream is) throws IOException { - return is; - } - - /** - * Create an ObjectInputStream for the given InputStream and codebase. - * The default implementation creates a CodebaseAwareObjectInputStream. - * @param is the InputStream to read from - * @param codebaseUrl the codebase URL to load classes from if not found locally - * (can be {@code null}) - * @return the new ObjectInputStream instance to use - * @throws IOException if creation of the ObjectInputStream failed - * @see com.fr.third.springframework.remoting.rmi.CodebaseAwareObjectInputStream - */ - protected ObjectInputStream createObjectInputStream(InputStream is, String codebaseUrl) throws IOException { - return new CodebaseAwareObjectInputStream(is, getBeanClassLoader(), codebaseUrl); - } - - /** - * Perform the actual reading of an invocation object from the - * given ObjectInputStream. - *

The default implementation simply calls {@code readObject}. - * Can be overridden for deserialization of a custom wrapper object rather - * than the plain invocation, for example an encryption-aware holder. - * @param ois the ObjectInputStream to read from - * @return the RemoteInvocationResult object - * @throws IOException if thrown by I/O methods - * @throws ClassNotFoundException if the class name of a serialized object - * couldn't get resolved - * @see java.io.ObjectOutputStream#writeObject - */ - protected RemoteInvocationResult doReadRemoteInvocationResult(ObjectInputStream ois) - throws IOException, ClassNotFoundException { - - Object obj = ois.readObject(); - if (!(obj instanceof RemoteInvocationResult)) { - throw new RemoteException("Deserialized object needs to be assignable to type [" + - RemoteInvocationResult.class.getName() + "]: " + ClassUtils.getDescriptiveType(obj)); - } - return (RemoteInvocationResult) obj; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java deleted file mode 100644 index 46eaa8335..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; -import java.util.zip.GZIPInputStream; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.http.NoHttpResponseException; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.Configurable; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; - -import com.fr.third.springframework.context.i18n.LocaleContext; -import com.fr.third.springframework.context.i18n.LocaleContextHolder; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; -import com.fr.third.springframework.util.Assert; -import com.fr.third.springframework.util.ClassUtils; -import com.fr.third.springframework.util.StringUtils; - -/** - * {@link com.fr.third.springframework.remoting.httpinvoker.HttpInvokerRequestExecutor} implementation that uses - * Apache HttpComponents HttpClient - * to execute POST requests. - * - *

Allows to use a pre-configured {@link org.apache.http.client.HttpClient} - * instance, potentially with authentication, HTTP connection pooling, etc. - * Also designed for easy subclassing, providing specific template methods. - * - *

As of Spring 4.1, this request executor requires Apache HttpComponents 4.3 or higher. - * - * @author Juergen Hoeller - * @author Stephane Nicoll - * @since 3.1 - * @see com.fr.third.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor - */ -public class HttpComponentsHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor { - - private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100; - - private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5; - - private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000); - - - private static Class abstractHttpClientClass; - - static { - try { - // Looking for AbstractHttpClient class (deprecated as of HttpComponents 4.3) - abstractHttpClientClass = ClassUtils.forName("org.apache.http.impl.client.AbstractHttpClient", - HttpComponentsHttpInvokerRequestExecutor.class.getClassLoader()); - } - catch (ClassNotFoundException ex) { - // Probably removed from HttpComponents in the meantime... - } - } - - - private HttpClient httpClient; - - private RequestConfig requestConfig; - - - /** - * Create a new instance of the HttpComponentsHttpInvokerRequestExecutor with a default - * {@link HttpClient} that uses a default {@code org.apache.http.impl.conn.PoolingClientConnectionManager}. - */ - public HttpComponentsHttpInvokerRequestExecutor() { - this(createDefaultHttpClient(), RequestConfig.custom() - .setSocketTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS).build()); - } - - /** - * Create a new instance of the HttpComponentsClientHttpRequestFactory - * with the given {@link HttpClient} instance. - * @param httpClient the HttpClient instance to use for this request executor - */ - public HttpComponentsHttpInvokerRequestExecutor(HttpClient httpClient) { - this(httpClient, null); - } - - private HttpComponentsHttpInvokerRequestExecutor(HttpClient httpClient, RequestConfig requestConfig) { - this.httpClient = httpClient; - this.requestConfig = requestConfig; - } - - - private static HttpClient createDefaultHttpClient() { - Registry schemeRegistry = RegistryBuilder.create() - .register("http", PlainConnectionSocketFactory.getSocketFactory()) - .register("https", SSLConnectionSocketFactory.getSocketFactory()) - .build(); - - PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(schemeRegistry); - connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS); - connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE); - - return HttpClientBuilder.create().setConnectionManager(connectionManager).build(); - } - - - /** - * Set the {@link HttpClient} instance to use for this request executor. - */ - public void setHttpClient(HttpClient httpClient) { - this.httpClient = httpClient; - } - - /** - * Return the {@link HttpClient} instance that this request executor uses. - */ - public HttpClient getHttpClient() { - return this.httpClient; - } - - /** - * Set the connection timeout for the underlying HttpClient. - * A timeout value of 0 specifies an infinite timeout. - *

Additional properties can be configured by specifying a - * {@link RequestConfig} instance on a custom {@link HttpClient}. - * @param timeout the timeout value in milliseconds - * @see RequestConfig#getConnectTimeout() - */ - public void setConnectTimeout(int timeout) { - Assert.isTrue(timeout >= 0, "Timeout must be a non-negative value"); - this.requestConfig = cloneRequestConfig().setConnectTimeout(timeout).build(); - setLegacyConnectionTimeout(getHttpClient(), timeout); - } - - /** - * Apply the specified connection timeout to deprecated {@link HttpClient} - * implementations. - *

As of HttpClient 4.3, default parameters have to be exposed through a - * {@link RequestConfig} instance instead of setting the parameters on the - * client. Unfortunately, this behavior is not backward-compatible and older - * {@link HttpClient} implementations will ignore the {@link RequestConfig} - * object set in the context. - *

If the specified client is an older implementation, we set the custom - * connection timeout through the deprecated API. Otherwise, we just return - * as it is set through {@link RequestConfig} with newer clients. - * @param client the client to configure - * @param timeout the custom connection timeout - */ - @SuppressWarnings("deprecation") - private void setLegacyConnectionTimeout(HttpClient client, int timeout) { - if (abstractHttpClientClass != null && abstractHttpClientClass.isInstance(client)) { - client.getParams().setIntParameter(org.apache.http.params.CoreConnectionPNames.CONNECTION_TIMEOUT, timeout); - } - } - - /** - * Set the timeout in milliseconds used when requesting a connection from the connection - * manager using the underlying HttpClient. - * A timeout value of 0 specifies an infinite timeout. - *

Additional properties can be configured by specifying a - * {@link RequestConfig} instance on a custom {@link HttpClient}. - * @param connectionRequestTimeout the timeout value to request a connection in milliseconds - * @see RequestConfig#getConnectionRequestTimeout() - */ - public void setConnectionRequestTimeout(int connectionRequestTimeout) { - this.requestConfig = cloneRequestConfig().setConnectionRequestTimeout(connectionRequestTimeout).build(); - } - - /** - * Set the socket read timeout for the underlying HttpClient. - * A timeout value of 0 specifies an infinite timeout. - *

Additional properties can be configured by specifying a - * {@link RequestConfig} instance on a custom {@link HttpClient}. - * @param timeout the timeout value in milliseconds - * @see #DEFAULT_READ_TIMEOUT_MILLISECONDS - * @see RequestConfig#getSocketTimeout() - */ - public void setReadTimeout(int timeout) { - Assert.isTrue(timeout >= 0, "Timeout must be a non-negative value"); - this.requestConfig = cloneRequestConfig().setSocketTimeout(timeout).build(); - setLegacySocketTimeout(getHttpClient(), timeout); - } - - /** - * Apply the specified socket timeout to deprecated {@link HttpClient} - * implementations. See {@link #setLegacyConnectionTimeout}. - * @param client the client to configure - * @param timeout the custom socket timeout - * @see #setLegacyConnectionTimeout - */ - @SuppressWarnings("deprecation") - private void setLegacySocketTimeout(HttpClient client, int timeout) { - if (abstractHttpClientClass != null && abstractHttpClientClass.isInstance(client)) { - client.getParams().setIntParameter(org.apache.http.params.CoreConnectionPNames.SO_TIMEOUT, timeout); - } - } - - private RequestConfig.Builder cloneRequestConfig() { - return (this.requestConfig != null ? RequestConfig.copy(this.requestConfig) : RequestConfig.custom()); - } - - - /** - * Execute the given request through the HttpClient. - *

This method implements the basic processing workflow: - * The actual work happens in this class's template methods. - * @see #createHttpPost - * @see #setRequestBody - * @see #executeHttpPost - * @see #validateResponse - * @see #getResponseBody - */ - @Override - protected RemoteInvocationResult doExecuteRequest( - HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) - throws IOException, ClassNotFoundException { - - HttpPost postMethod = createHttpPost(config); - setRequestBody(config, postMethod, baos); - try { - HttpResponse response = executeHttpPost(config, getHttpClient(), postMethod); - validateResponse(config, response); - InputStream responseBody = getResponseBody(config, response); - return readRemoteInvocationResult(responseBody, config.getCodebaseUrl()); - } - finally { - postMethod.releaseConnection(); - } - } - - /** - * Create a HttpPost for the given configuration. - *

The default implementation creates a standard HttpPost with - * "application/x-java-serialized-object" as "Content-Type" header. - * @param config the HTTP invoker configuration that specifies the - * target service - * @return the HttpPost instance - * @throws java.io.IOException if thrown by I/O methods - */ - protected HttpPost createHttpPost(HttpInvokerClientConfiguration config) throws IOException { - HttpPost httpPost = new HttpPost(config.getServiceUrl()); - - RequestConfig requestConfig = createRequestConfig(config); - if (requestConfig != null) { - httpPost.setConfig(requestConfig); - } - - LocaleContext localeContext = LocaleContextHolder.getLocaleContext(); - if (localeContext != null) { - Locale locale = localeContext.getLocale(); - if (locale != null) { - httpPost.addHeader(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale)); - } - } - - if (isAcceptGzipEncoding()) { - httpPost.addHeader(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP); - } - - return httpPost; - } - - /** - * Create a {@link RequestConfig} for the given configuration. Can return {@code null} - * to indicate that no custom request config should be set and the defaults of the - * {@link HttpClient} should be used. - *

The default implementation tries to merge the defaults of the client with the - * local customizations of the instance, if any. - * @param config the HTTP invoker configuration that specifies the - * target service - * @return the RequestConfig to use - */ - protected RequestConfig createRequestConfig(HttpInvokerClientConfiguration config) { - HttpClient client = getHttpClient(); - if (client instanceof Configurable) { - RequestConfig clientRequestConfig = ((Configurable) client).getConfig(); - return mergeRequestConfig(clientRequestConfig); - } - return this.requestConfig; - } - - private RequestConfig mergeRequestConfig(RequestConfig defaultRequestConfig) { - if (this.requestConfig == null) { // nothing to merge - return defaultRequestConfig; - } - - RequestConfig.Builder builder = RequestConfig.copy(defaultRequestConfig); - int connectTimeout = this.requestConfig.getConnectTimeout(); - if (connectTimeout >= 0) { - builder.setConnectTimeout(connectTimeout); - } - int connectionRequestTimeout = this.requestConfig.getConnectionRequestTimeout(); - if (connectionRequestTimeout >= 0) { - builder.setConnectionRequestTimeout(connectionRequestTimeout); - } - int socketTimeout = this.requestConfig.getSocketTimeout(); - if (socketTimeout >= 0) { - builder.setSocketTimeout(socketTimeout); - } - return builder.build(); - } - - /** - * Set the given serialized remote invocation as request body. - *

The default implementation simply sets the serialized invocation as the - * HttpPost's request body. This can be overridden, for example, to write a - * specific encoding and to potentially set appropriate HTTP request headers. - * @param config the HTTP invoker configuration that specifies the target service - * @param httpPost the HttpPost to set the request body on - * @param baos the ByteArrayOutputStream that contains the serialized - * RemoteInvocation object - * @throws java.io.IOException if thrown by I/O methods - */ - protected void setRequestBody( - HttpInvokerClientConfiguration config, HttpPost httpPost, ByteArrayOutputStream baos) - throws IOException { - - ByteArrayEntity entity = new ByteArrayEntity(baos.toByteArray()); - entity.setContentType(getContentType()); - httpPost.setEntity(entity); - } - - /** - * Execute the given HttpPost instance. - * @param config the HTTP invoker configuration that specifies the target service - * @param httpClient the HttpClient to execute on - * @param httpPost the HttpPost to execute - * @return the resulting HttpResponse - * @throws java.io.IOException if thrown by I/O methods - */ - protected HttpResponse executeHttpPost( - HttpInvokerClientConfiguration config, HttpClient httpClient, HttpPost httpPost) - throws IOException { - - return httpClient.execute(httpPost); - } - - /** - * Validate the given response as contained in the HttpPost object, - * throwing an exception if it does not correspond to a successful HTTP response. - *

Default implementation rejects any HTTP status code beyond 2xx, to avoid - * parsing the response body and trying to deserialize from a corrupted stream. - * @param config the HTTP invoker configuration that specifies the target service - * @param response the resulting HttpResponse to validate - * @throws java.io.IOException if validation failed - */ - protected void validateResponse(HttpInvokerClientConfiguration config, HttpResponse response) - throws IOException { - - StatusLine status = response.getStatusLine(); - if (status.getStatusCode() >= 300) { - throw new NoHttpResponseException( - "Did not receive successful HTTP response: status code = " + status.getStatusCode() + - ", status message = [" + status.getReasonPhrase() + "]"); - } - } - - /** - * Extract the response body from the given executed remote invocation request. - *

The default implementation simply fetches the HttpPost's response body stream. - * If the response is recognized as GZIP response, the InputStream will get wrapped - * in a GZIPInputStream. - * @param config the HTTP invoker configuration that specifies the target service - * @param httpResponse the resulting HttpResponse to read the response body from - * @return an InputStream for the response body - * @throws java.io.IOException if thrown by I/O methods - * @see #isGzipResponse - * @see java.util.zip.GZIPInputStream - */ - protected InputStream getResponseBody(HttpInvokerClientConfiguration config, HttpResponse httpResponse) - throws IOException { - - if (isGzipResponse(httpResponse)) { - return new GZIPInputStream(httpResponse.getEntity().getContent()); - } - else { - return httpResponse.getEntity().getContent(); - } - } - - /** - * Determine whether the given response indicates a GZIP response. - *

The default implementation checks whether the HTTP "Content-Encoding" - * header contains "gzip" (in any casing). - * @param httpResponse the resulting HttpResponse to check - * @return whether the given response indicates a GZIP response - */ - protected boolean isGzipResponse(HttpResponse httpResponse) { - Header encodingHeader = httpResponse.getFirstHeader(HTTP_HEADER_CONTENT_ENCODING); - return (encodingHeader != null && encodingHeader.getValue() != null && - encodingHeader.getValue().toLowerCase().contains(ENCODING_GZIP)); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java deleted file mode 100644 index 25f0f0b1b..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -/** - * Configuration interface for executing HTTP invoker requests. - * - * @author Juergen Hoeller - * @since 1.1 - * @see HttpInvokerRequestExecutor - * @see HttpInvokerClientInterceptor - */ -public interface HttpInvokerClientConfiguration { - - /** - * Return the HTTP URL of the target service. - */ - String getServiceUrl(); - - /** - * Return the codebase URL to download classes from if not found locally. - * Can consist of multiple URLs, separated by spaces. - * @return the codebase URL, or {@code null} if none - * @see java.rmi.server.RMIClassLoader - */ - String getCodebaseUrl(); - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java deleted file mode 100644 index 827cc4ffe..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import java.io.IOException; -import java.io.InvalidClassException; -import java.net.ConnectException; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import com.fr.third.springframework.aop.support.AopUtils; -import com.fr.third.springframework.remoting.RemoteAccessException; -import com.fr.third.springframework.remoting.RemoteConnectFailureException; -import com.fr.third.springframework.remoting.RemoteInvocationFailureException; -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationBasedAccessor; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; - -/** - * {@link org.aopalliance.intercept.MethodInterceptor} for accessing an - * HTTP invoker service. The service URL must be an HTTP URL exposing - * an HTTP invoker service. - * - *

Serializes remote invocation objects and deserializes remote invocation - * result objects. Uses Java serialization just like RMI, but provides the - * same ease of setup as Caucho's HTTP-based Hessian and Burlap protocols. - * - *

HTTP invoker is a very extensible and customizable protocol. - * It supports the RemoteInvocationFactory mechanism, like RMI invoker, - * allowing to include additional invocation attributes (for example, - * a security context). Furthermore, it allows to customize request - * execution via the {@link HttpInvokerRequestExecutor} strategy. - * - *

Can use the JDK's {@link java.rmi.server.RMIClassLoader} to load classes - * from a given {@link #setCodebaseUrl codebase}, performing on-demand dynamic - * code download from a remote location. The codebase can consist of multiple - * URLs, separated by spaces. Note that RMIClassLoader requires a SecurityManager - * to be set, analogous to when using dynamic class download with standard RMI! - * (See the RMI documentation for details.) - * - *

WARNING: Be aware of vulnerabilities due to unsafe Java deserialization: - * Manipulated input streams could lead to unwanted code execution on the server - * during the deserialization step. As a consequence, do not expose HTTP invoker - * endpoints to untrusted clients but rather just between your own services. - * In general, we strongly recommend any other message format (e.g. JSON) instead. - * - * @author Juergen Hoeller - * @since 1.1 - * @see #setServiceUrl - * @see #setCodebaseUrl - * @see #setRemoteInvocationFactory - * @see #setHttpInvokerRequestExecutor - * @see HttpInvokerServiceExporter - * @see HttpInvokerProxyFactoryBean - * @see java.rmi.server.RMIClassLoader - */ -public class HttpInvokerClientInterceptor extends RemoteInvocationBasedAccessor - implements MethodInterceptor, HttpInvokerClientConfiguration { - - private String codebaseUrl; - - private HttpInvokerRequestExecutor httpInvokerRequestExecutor; - - - /** - * Set the codebase URL to download classes from if not found locally. - * Can consists of multiple URLs, separated by spaces. - *

Follows RMI's codebase conventions for dynamic class download. - * In contrast to RMI, where the server determines the URL for class download - * (via the "java.rmi.server.codebase" system property), it's the client - * that determines the codebase URL here. The server will usually be the - * same as for the service URL, just pointing to a different path there. - * @see #setServiceUrl - * @see com.fr.third.springframework.remoting.rmi.CodebaseAwareObjectInputStream - * @see java.rmi.server.RMIClassLoader - */ - public void setCodebaseUrl(String codebaseUrl) { - this.codebaseUrl = codebaseUrl; - } - - /** - * Return the codebase URL to download classes from if not found locally. - */ - @Override - public String getCodebaseUrl() { - return this.codebaseUrl; - } - - /** - * Set the HttpInvokerRequestExecutor implementation to use for executing - * remote invocations. - *

Default is {@link SimpleHttpInvokerRequestExecutor}. Alternatively, - * consider using {@link HttpComponentsHttpInvokerRequestExecutor} for more - * sophisticated needs. - * @see SimpleHttpInvokerRequestExecutor - * @see HttpComponentsHttpInvokerRequestExecutor - */ - public void setHttpInvokerRequestExecutor(HttpInvokerRequestExecutor httpInvokerRequestExecutor) { - this.httpInvokerRequestExecutor = httpInvokerRequestExecutor; - } - - /** - * Return the HttpInvokerRequestExecutor used by this remote accessor. - *

Creates a default SimpleHttpInvokerRequestExecutor if no executor - * has been initialized already. - */ - public HttpInvokerRequestExecutor getHttpInvokerRequestExecutor() { - if (this.httpInvokerRequestExecutor == null) { - SimpleHttpInvokerRequestExecutor executor = new SimpleHttpInvokerRequestExecutor(); - executor.setBeanClassLoader(getBeanClassLoader()); - this.httpInvokerRequestExecutor = executor; - } - return this.httpInvokerRequestExecutor; - } - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - - // Eagerly initialize the default HttpInvokerRequestExecutor, if needed. - getHttpInvokerRequestExecutor(); - } - - - @Override - public Object invoke(MethodInvocation methodInvocation) throws Throwable { - if (AopUtils.isToStringMethod(methodInvocation.getMethod())) { - return "HTTP invoker proxy for service URL [" + getServiceUrl() + "]"; - } - - RemoteInvocation invocation = createRemoteInvocation(methodInvocation); - RemoteInvocationResult result; - - try { - result = executeRequest(invocation, methodInvocation); - } - catch (Throwable ex) { - RemoteAccessException rae = convertHttpInvokerAccessException(ex); - throw (rae != null ? rae : ex); - } - - try { - return recreateRemoteInvocationResult(result); - } - catch (Throwable ex) { - if (result.hasInvocationTargetException()) { - throw ex; - } - else { - throw new RemoteInvocationFailureException("Invocation of method [" + methodInvocation.getMethod() + - "] failed in HTTP invoker remote service at [" + getServiceUrl() + "]", ex); - } - } - } - - /** - * Execute the given remote invocation via the {@link HttpInvokerRequestExecutor}. - *

This implementation delegates to {@link #executeRequest(RemoteInvocation)}. - * Can be overridden to react to the specific original MethodInvocation. - * @param invocation the RemoteInvocation to execute - * @param originalInvocation the original MethodInvocation (can e.g. be cast - * to the ProxyMethodInvocation interface for accessing user attributes) - * @return the RemoteInvocationResult object - * @throws Exception in case of errors - */ - protected RemoteInvocationResult executeRequest( - RemoteInvocation invocation, MethodInvocation originalInvocation) throws Exception { - - return executeRequest(invocation); - } - - /** - * Execute the given remote invocation via the {@link HttpInvokerRequestExecutor}. - *

Can be overridden in subclasses to pass a different configuration object - * to the executor. Alternatively, add further configuration properties in a - * subclass of this accessor: By default, the accessor passed itself as - * configuration object to the executor. - * @param invocation the RemoteInvocation to execute - * @return the RemoteInvocationResult object - * @throws IOException if thrown by I/O operations - * @throws ClassNotFoundException if thrown during deserialization - * @throws Exception in case of general errors - * @see #getHttpInvokerRequestExecutor - * @see HttpInvokerClientConfiguration - */ - protected RemoteInvocationResult executeRequest(RemoteInvocation invocation) throws Exception { - return getHttpInvokerRequestExecutor().executeRequest(this, invocation); - } - - /** - * Convert the given HTTP invoker access exception to an appropriate - * Spring {@link RemoteAccessException}. - * @param ex the exception to convert - * @return the RemoteAccessException to throw, or {@code null} to have the - * original exception propagated to the caller - */ - protected RemoteAccessException convertHttpInvokerAccessException(Throwable ex) { - if (ex instanceof ConnectException) { - return new RemoteConnectFailureException( - "Could not connect to HTTP invoker remote service at [" + getServiceUrl() + "]", ex); - } - - if (ex instanceof ClassNotFoundException || ex instanceof NoClassDefFoundError || - ex instanceof InvalidClassException) { - return new RemoteAccessException( - "Could not deserialize result from HTTP invoker remote service [" + getServiceUrl() + "]", ex); - } - - if (ex instanceof Exception) { - return new RemoteAccessException( - "Could not access HTTP invoker remote service at [" + getServiceUrl() + "]", ex); - } - - // For any other Throwable, e.g. OutOfMemoryError: let it get propagated as-is. - return null; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java deleted file mode 100644 index 649facc56..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import com.fr.third.springframework.aop.framework.ProxyFactory; -import com.fr.third.springframework.beans.factory.FactoryBean; - -/** - * {@link FactoryBean} for HTTP invoker proxies. Exposes the proxied service - * for use as a bean reference, using the specified service interface. - * - *

The service URL must be an HTTP URL exposing an HTTP invoker service. - * Optionally, a codebase URL can be specified for on-demand dynamic code download - * from a remote location. For details, see HttpInvokerClientInterceptor docs. - * - *

Serializes remote invocation objects and deserializes remote invocation - * result objects. Uses Java serialization just like RMI, but provides the - * same ease of setup as Caucho's HTTP-based Hessian and Burlap protocols. - * - *

HTTP invoker is the recommended protocol for Java-to-Java remoting. - * It is more powerful and more extensible than Hessian and Burlap, at the - * expense of being tied to Java. Nevertheless, it is as easy to set up as - * Hessian and Burlap, which is its main advantage compared to RMI. - * - *

WARNING: Be aware of vulnerabilities due to unsafe Java deserialization: - * Manipulated input streams could lead to unwanted code execution on the server - * during the deserialization step. As a consequence, do not expose HTTP invoker - * endpoints to untrusted clients but rather just between your own services. - * In general, we strongly recommend any other message format (e.g. JSON) instead. - * - * @author Juergen Hoeller - * @since 1.1 - * @see #setServiceInterface - * @see #setServiceUrl - * @see #setCodebaseUrl - * @see HttpInvokerClientInterceptor - * @see HttpInvokerServiceExporter - * @see com.fr.third.springframework.remoting.rmi.RmiProxyFactoryBean - * @see com.fr.third.springframework.remoting.caucho.HessianProxyFactoryBean - * @see com.fr.third.springframework.remoting.caucho.BurlapProxyFactoryBean - */ -public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor implements FactoryBean { - - private Object serviceProxy; - - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - if (getServiceInterface() == null) { - throw new IllegalArgumentException("Property 'serviceInterface' is required"); - } - this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader()); - } - - - @Override - public Object getObject() { - return this.serviceProxy; - } - - @Override - public Class getObjectType() { - return getServiceInterface(); - } - - @Override - public boolean isSingleton() { - return true; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java deleted file mode 100644 index 7dd3d6bc6..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2002-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import java.io.IOException; - -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; - -/** - * Strategy interface for actual execution of an HTTP invoker request. - * Used by HttpInvokerClientInterceptor and its subclass - * HttpInvokerProxyFactoryBean. - * - *

Two implementations are provided out of the box: - *

    - *
  • {@code SimpleHttpInvokerRequestExecutor}: - * Uses JDK facilities to execute POST requests, without support - * for HTTP authentication or advanced configuration options. - *
  • {@code HttpComponentsHttpInvokerRequestExecutor}: - * Uses Apache's Commons HttpClient to execute POST requests, - * allowing to use a preconfigured HttpClient instance - * (potentially with authentication, HTTP connection pooling, etc). - *
- * - * @author Juergen Hoeller - * @since 1.1 - * @see HttpInvokerClientInterceptor#setHttpInvokerRequestExecutor - */ -public interface HttpInvokerRequestExecutor { - - /** - * Execute a request to send the given remote invocation. - * @param config the HTTP invoker configuration that specifies the - * target service - * @param invocation the RemoteInvocation to execute - * @return the RemoteInvocationResult object - * @throws IOException if thrown by I/O operations - * @throws ClassNotFoundException if thrown during deserialization - * @throws Exception in case of general errors - */ - RemoteInvocationResult executeRequest(HttpInvokerClientConfiguration config, RemoteInvocation invocation) - throws Exception; - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java deleted file mode 100644 index 024065838..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.fr.third.springframework.remoting.rmi.RemoteInvocationSerializingExporter; -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; -import com.fr.third.springframework.web.HttpRequestHandler; -import com.fr.third.springframework.web.util.NestedServletException; - -/** - * Servlet-API-based HTTP request handler that exports the specified service bean - * as HTTP invoker service endpoint, accessible via an HTTP invoker proxy. - * - *

Note: Spring also provides an alternative version of this exporter, - * for Sun's JRE 1.6 HTTP server: {@link SimpleHttpInvokerServiceExporter}. - * - *

Deserializes remote invocation objects and serializes remote invocation - * result objects. Uses Java serialization just like RMI, but provides the - * same ease of setup as Caucho's HTTP-based Hessian and Burlap protocols. - * - *

HTTP invoker is the recommended protocol for Java-to-Java remoting. - * It is more powerful and more extensible than Hessian and Burlap, at the - * expense of being tied to Java. Nevertheless, it is as easy to set up as - * Hessian and Burlap, which is its main advantage compared to RMI. - * - *

WARNING: Be aware of vulnerabilities due to unsafe Java deserialization: - * Manipulated input streams could lead to unwanted code execution on the server - * during the deserialization step. As a consequence, do not expose HTTP invoker - * endpoints to untrusted clients but rather just between your own services. - * In general, we strongly recommend any other message format (e.g. JSON) instead. - * - * @author Juergen Hoeller - * @since 1.1 - * @see HttpInvokerClientInterceptor - * @see HttpInvokerProxyFactoryBean - * @see com.fr.third.springframework.remoting.rmi.RmiServiceExporter - * @see com.fr.third.springframework.remoting.caucho.HessianServiceExporter - * @see com.fr.third.springframework.remoting.caucho.BurlapServiceExporter - */ -public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpRequestHandler { - - /** - * Reads a remote invocation from the request, executes it, - * and writes the remote invocation result to the response. - * @see #readRemoteInvocation(HttpServletRequest) - * @see #invokeAndCreateResult(org.springframework.remoting.support.RemoteInvocation, Object) - * @see #writeRemoteInvocationResult(HttpServletRequest, HttpServletResponse, RemoteInvocationResult) - */ - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - try { - RemoteInvocation invocation = readRemoteInvocation(request); - RemoteInvocationResult result = invokeAndCreateResult(invocation, getProxy()); - writeRemoteInvocationResult(request, response, result); - } - catch (ClassNotFoundException ex) { - throw new NestedServletException("Class not found during deserialization", ex); - } - } - - /** - * Read a RemoteInvocation from the given HTTP request. - *

Delegates to {@link #readRemoteInvocation(HttpServletRequest, InputStream)} with - * the {@link HttpServletRequest#getInputStream() servlet request's input stream}. - * @param request current HTTP request - * @return the RemoteInvocation object - * @throws IOException in case of I/O failure - * @throws ClassNotFoundException if thrown by deserialization - */ - protected RemoteInvocation readRemoteInvocation(HttpServletRequest request) - throws IOException, ClassNotFoundException { - - return readRemoteInvocation(request, request.getInputStream()); - } - - /** - * Deserialize a RemoteInvocation object from the given InputStream. - *

Gives {@link #decorateInputStream} a chance to decorate the stream - * first (for example, for custom encryption or compression). Creates a - * {@link com.fr.third.springframework.remoting.rmi.CodebaseAwareObjectInputStream} - * and calls {@link #doReadRemoteInvocation} to actually read the object. - *

Can be overridden for custom serialization of the invocation. - * @param request current HTTP request - * @param is the InputStream to read from - * @return the RemoteInvocation object - * @throws IOException in case of I/O failure - * @throws ClassNotFoundException if thrown during deserialization - */ - protected RemoteInvocation readRemoteInvocation(HttpServletRequest request, InputStream is) - throws IOException, ClassNotFoundException { - - ObjectInputStream ois = createObjectInputStream(decorateInputStream(request, is)); - try { - return doReadRemoteInvocation(ois); - } - finally { - ois.close(); - } - } - - /** - * Return the InputStream to use for reading remote invocations, - * potentially decorating the given original InputStream. - *

The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param request current HTTP request - * @param is the original InputStream - * @return the potentially decorated InputStream - * @throws IOException in case of I/O failure - */ - protected InputStream decorateInputStream(HttpServletRequest request, InputStream is) throws IOException { - return is; - } - - /** - * Write the given RemoteInvocationResult to the given HTTP response. - * @param request current HTTP request - * @param response current HTTP response - * @param result the RemoteInvocationResult object - * @throws IOException in case of I/O failure - */ - protected void writeRemoteInvocationResult( - HttpServletRequest request, HttpServletResponse response, RemoteInvocationResult result) - throws IOException { - - response.setContentType(getContentType()); - writeRemoteInvocationResult(request, response, result, response.getOutputStream()); - } - - /** - * Serialize the given RemoteInvocation to the given OutputStream. - *

The default implementation gives {@link #decorateOutputStream} a chance - * to decorate the stream first (for example, for custom encryption or compression). - * Creates an {@link java.io.ObjectOutputStream} for the final stream and calls - * {@link #doWriteRemoteInvocationResult} to actually write the object. - *

Can be overridden for custom serialization of the invocation. - * @param request current HTTP request - * @param response current HTTP response - * @param result the RemoteInvocationResult object - * @param os the OutputStream to write to - * @throws IOException in case of I/O failure - * @see #decorateOutputStream - * @see #doWriteRemoteInvocationResult - */ - protected void writeRemoteInvocationResult( - HttpServletRequest request, HttpServletResponse response, RemoteInvocationResult result, OutputStream os) - throws IOException { - - ObjectOutputStream oos = - createObjectOutputStream(new FlushGuardedOutputStream(decorateOutputStream(request, response, os))); - try { - doWriteRemoteInvocationResult(result, oos); - } - finally { - oos.close(); - } - } - - /** - * Return the OutputStream to use for writing remote invocation results, - * potentially decorating the given original OutputStream. - *

The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param request current HTTP request - * @param response current HTTP response - * @param os the original OutputStream - * @return the potentially decorated OutputStream - * @throws IOException in case of I/O failure - */ - protected OutputStream decorateOutputStream( - HttpServletRequest request, HttpServletResponse response, OutputStream os) throws IOException { - - return os; - } - - - /** - * Decorate an {@code OutputStream} to guard against {@code flush()} calls, - * which are turned into no-ops. - *

Because {@link ObjectOutputStream#close()} will in fact flush/drain - * the underlying stream twice, this {@link FilterOutputStream} will - * guard against individual flush calls. Multiple flush calls can lead - * to performance issues, since writes aren't gathered as they should be. - * @see SPR-14040 - */ - private static class FlushGuardedOutputStream extends FilterOutputStream { - - public FlushGuardedOutputStream(OutputStream out) { - super(out); - } - - @Override - public void flush() throws IOException { - // Do nothing on flush - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java deleted file mode 100644 index 43959fdb1..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; -import java.util.Locale; -import java.util.zip.GZIPInputStream; - -import com.fr.third.springframework.context.i18n.LocaleContext; -import com.fr.third.springframework.context.i18n.LocaleContextHolder; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; -import com.fr.third.springframework.util.StringUtils; - -/** - * {@link com.fr.third.springframework.remoting.httpinvoker.HttpInvokerRequestExecutor} implementation - * that uses standard Java facilities to execute POST requests, without support for HTTP - * authentication or advanced configuration options. - * - *

Designed for easy subclassing, customizing specific template methods. However, - * consider {@code HttpComponentsHttpInvokerRequestExecutor} for more sophisticated needs: - * The standard {@link HttpURLConnection} class is rather limited in its capabilities. - * - * @author Juergen Hoeller - * @since 1.1 - * @see java.net.HttpURLConnection - */ -public class SimpleHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor { - - private int connectTimeout = -1; - - private int readTimeout = -1; - - - /** - * Set the underlying URLConnection's connect timeout (in milliseconds). - * A timeout value of 0 specifies an infinite timeout. - *

Default is the system's default timeout. - * @see URLConnection#setConnectTimeout(int) - */ - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - } - - /** - * Set the underlying URLConnection's read timeout (in milliseconds). - * A timeout value of 0 specifies an infinite timeout. - *

Default is the system's default timeout. - * @see URLConnection#setReadTimeout(int) - */ - public void setReadTimeout(int readTimeout) { - this.readTimeout = readTimeout; - } - - - /** - * Execute the given request through a standard {@link HttpURLConnection}. - *

This method implements the basic processing workflow: - * The actual work happens in this class's template methods. - * @see #openConnection - * @see #prepareConnection - * @see #writeRequestBody - * @see #validateResponse - * @see #readResponseBody - */ - @Override - protected RemoteInvocationResult doExecuteRequest( - HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) - throws IOException, ClassNotFoundException { - - HttpURLConnection con = openConnection(config); - prepareConnection(con, baos.size()); - writeRequestBody(config, con, baos); - validateResponse(config, con); - InputStream responseBody = readResponseBody(config, con); - - return readRemoteInvocationResult(responseBody, config.getCodebaseUrl()); - } - - /** - * Open an {@link HttpURLConnection} for the given remote invocation request. - * @param config the HTTP invoker configuration that specifies the - * target service - * @return the HttpURLConnection for the given request - * @throws IOException if thrown by I/O methods - * @see java.net.URL#openConnection() - */ - protected HttpURLConnection openConnection(HttpInvokerClientConfiguration config) throws IOException { - URLConnection con = new URL(config.getServiceUrl()).openConnection(); - if (!(con instanceof HttpURLConnection)) { - throw new IOException( - "Service URL [" + config.getServiceUrl() + "] does not resolve to an HTTP connection"); - } - return (HttpURLConnection) con; - } - - /** - * Prepare the given HTTP connection. - *

The default implementation specifies POST as method, - * "application/x-java-serialized-object" as "Content-Type" header, - * and the given content length as "Content-Length" header. - * @param connection the HTTP connection to prepare - * @param contentLength the length of the content to send - * @throws IOException if thrown by HttpURLConnection methods - * @see java.net.HttpURLConnection#setRequestMethod - * @see java.net.HttpURLConnection#setRequestProperty - */ - protected void prepareConnection(HttpURLConnection connection, int contentLength) throws IOException { - if (this.connectTimeout >= 0) { - connection.setConnectTimeout(this.connectTimeout); - } - if (this.readTimeout >= 0) { - connection.setReadTimeout(this.readTimeout); - } - - connection.setDoOutput(true); - connection.setRequestMethod(HTTP_METHOD_POST); - connection.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, getContentType()); - connection.setRequestProperty(HTTP_HEADER_CONTENT_LENGTH, Integer.toString(contentLength)); - - LocaleContext localeContext = LocaleContextHolder.getLocaleContext(); - if (localeContext != null) { - Locale locale = localeContext.getLocale(); - if (locale != null) { - connection.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale)); - } - } - - if (isAcceptGzipEncoding()) { - connection.setRequestProperty(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP); - } - } - - /** - * Set the given serialized remote invocation as request body. - *

The default implementation simply write the serialized invocation to the - * HttpURLConnection's OutputStream. This can be overridden, for example, to write - * a specific encoding and potentially set appropriate HTTP request headers. - * @param config the HTTP invoker configuration that specifies the target service - * @param con the HttpURLConnection to write the request body to - * @param baos the ByteArrayOutputStream that contains the serialized - * RemoteInvocation object - * @throws IOException if thrown by I/O methods - * @see java.net.HttpURLConnection#getOutputStream() - * @see java.net.HttpURLConnection#setRequestProperty - */ - protected void writeRequestBody( - HttpInvokerClientConfiguration config, HttpURLConnection con, ByteArrayOutputStream baos) - throws IOException { - - baos.writeTo(con.getOutputStream()); - } - - /** - * Validate the given response as contained in the {@link HttpURLConnection} object, - * throwing an exception if it does not correspond to a successful HTTP response. - *

Default implementation rejects any HTTP status code beyond 2xx, to avoid - * parsing the response body and trying to deserialize from a corrupted stream. - * @param config the HTTP invoker configuration that specifies the target service - * @param con the HttpURLConnection to validate - * @throws IOException if validation failed - * @see java.net.HttpURLConnection#getResponseCode() - */ - protected void validateResponse(HttpInvokerClientConfiguration config, HttpURLConnection con) - throws IOException { - - if (con.getResponseCode() >= 300) { - throw new IOException( - "Did not receive successful HTTP response: status code = " + con.getResponseCode() + - ", status message = [" + con.getResponseMessage() + "]"); - } - } - - /** - * Extract the response body from the given executed remote invocation - * request. - *

The default implementation simply reads the serialized invocation - * from the HttpURLConnection's InputStream. If the response is recognized - * as GZIP response, the InputStream will get wrapped in a GZIPInputStream. - * @param config the HTTP invoker configuration that specifies the target service - * @param con the HttpURLConnection to read the response body from - * @return an InputStream for the response body - * @throws IOException if thrown by I/O methods - * @see #isGzipResponse - * @see java.util.zip.GZIPInputStream - * @see java.net.HttpURLConnection#getInputStream() - * @see java.net.HttpURLConnection#getHeaderField(int) - * @see java.net.HttpURLConnection#getHeaderFieldKey(int) - */ - protected InputStream readResponseBody(HttpInvokerClientConfiguration config, HttpURLConnection con) - throws IOException { - - if (isGzipResponse(con)) { - // GZIP response found - need to unzip. - return new GZIPInputStream(con.getInputStream()); - } - else { - // Plain response found. - return con.getInputStream(); - } - } - - /** - * Determine whether the given response is a GZIP response. - *

Default implementation checks whether the HTTP "Content-Encoding" - * header contains "gzip" (in any casing). - * @param con the HttpURLConnection to check - */ - protected boolean isGzipResponse(HttpURLConnection con) { - String encodingHeader = con.getHeaderField(HTTP_HEADER_CONTENT_ENCODING); - return (encodingHeader != null && encodingHeader.toLowerCase().contains(ENCODING_GZIP)); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java deleted file mode 100644 index 8fdcb87dd..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.httpinvoker; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - -import com.fr.third.springframework.lang.UsesSunHttpServer; -import com.fr.third.springframework.remoting.rmi.RemoteInvocationSerializingExporter; -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; - -/** - * HTTP request handler that exports the specified service bean as - * HTTP invoker service endpoint, accessible via an HTTP invoker proxy. - * Designed for Sun's JRE 1.6 HTTP server, implementing the - * {@link com.sun.net.httpserver.HttpHandler} interface. - * - *

Deserializes remote invocation objects and serializes remote invocation - * result objects. Uses Java serialization just like RMI, but provides the - * same ease of setup as Caucho's HTTP-based Hessian and Burlap protocols. - * - *

HTTP invoker is the recommended protocol for Java-to-Java remoting. - * It is more powerful and more extensible than Hessian and Burlap, at the - * expense of being tied to Java. Nevertheless, it is as easy to set up as - * Hessian and Burlap, which is its main advantage compared to RMI. - * - *

WARNING: Be aware of vulnerabilities due to unsafe Java deserialization: - * Manipulated input streams could lead to unwanted code execution on the server - * during the deserialization step. As a consequence, do not expose HTTP invoker - * endpoints to untrusted clients but rather just between your own services. - * In general, we strongly recommend any other message format (e.g. JSON) instead. - * - * @author Juergen Hoeller - * @since 2.5.1 - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean - * @see com.fr.third.springframework.remoting.caucho.SimpleHessianServiceExporter - * @see com.fr.third.springframework.remoting.caucho.SimpleBurlapServiceExporter - */ -@UsesSunHttpServer -public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpHandler { - - /** - * Reads a remote invocation from the request, executes it, - * and writes the remote invocation result to the response. - * @see #readRemoteInvocation(HttpExchange) - * @see #invokeAndCreateResult(RemoteInvocation, Object) - * @see #writeRemoteInvocationResult(HttpExchange, RemoteInvocationResult) - */ - @Override - public void handle(HttpExchange exchange) throws IOException { - try { - RemoteInvocation invocation = readRemoteInvocation(exchange); - RemoteInvocationResult result = invokeAndCreateResult(invocation, getProxy()); - writeRemoteInvocationResult(exchange, result); - exchange.close(); - } - catch (ClassNotFoundException ex) { - exchange.sendResponseHeaders(500, -1); - logger.error("Class not found during deserialization", ex); - } - } - - /** - * Read a RemoteInvocation from the given HTTP request. - *

Delegates to {@link #readRemoteInvocation(HttpExchange, InputStream)} - * with the {@link HttpExchange#getRequestBody()} request's input stream}. - * @param exchange current HTTP request/response - * @return the RemoteInvocation object - * @throws java.io.IOException in case of I/O failure - * @throws ClassNotFoundException if thrown by deserialization - */ - protected RemoteInvocation readRemoteInvocation(HttpExchange exchange) - throws IOException, ClassNotFoundException { - - return readRemoteInvocation(exchange, exchange.getRequestBody()); - } - - /** - * Deserialize a RemoteInvocation object from the given InputStream. - *

Gives {@link #decorateInputStream} a chance to decorate the stream - * first (for example, for custom encryption or compression). Creates a - * {@link com.fr.third.springframework.remoting.rmi.CodebaseAwareObjectInputStream} - * and calls {@link #doReadRemoteInvocation} to actually read the object. - *

Can be overridden for custom serialization of the invocation. - * @param exchange current HTTP request/response - * @param is the InputStream to read from - * @return the RemoteInvocation object - * @throws java.io.IOException in case of I/O failure - * @throws ClassNotFoundException if thrown during deserialization - */ - protected RemoteInvocation readRemoteInvocation(HttpExchange exchange, InputStream is) - throws IOException, ClassNotFoundException { - - ObjectInputStream ois = createObjectInputStream(decorateInputStream(exchange, is)); - return doReadRemoteInvocation(ois); - } - - /** - * Return the InputStream to use for reading remote invocations, - * potentially decorating the given original InputStream. - *

The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param exchange current HTTP request/response - * @param is the original InputStream - * @return the potentially decorated InputStream - * @throws java.io.IOException in case of I/O failure - */ - protected InputStream decorateInputStream(HttpExchange exchange, InputStream is) throws IOException { - return is; - } - - /** - * Write the given RemoteInvocationResult to the given HTTP response. - * @param exchange current HTTP request/response - * @param result the RemoteInvocationResult object - * @throws java.io.IOException in case of I/O failure - */ - protected void writeRemoteInvocationResult(HttpExchange exchange, RemoteInvocationResult result) - throws IOException { - - exchange.getResponseHeaders().set("Content-Type", getContentType()); - exchange.sendResponseHeaders(200, 0); - writeRemoteInvocationResult(exchange, result, exchange.getResponseBody()); - } - - /** - * Serialize the given RemoteInvocation to the given OutputStream. - *

The default implementation gives {@link #decorateOutputStream} a chance - * to decorate the stream first (for example, for custom encryption or compression). - * Creates an {@link java.io.ObjectOutputStream} for the final stream and calls - * {@link #doWriteRemoteInvocationResult} to actually write the object. - *

Can be overridden for custom serialization of the invocation. - * @param exchange current HTTP request/response - * @param result the RemoteInvocationResult object - * @param os the OutputStream to write to - * @throws java.io.IOException in case of I/O failure - * @see #decorateOutputStream - * @see #doWriteRemoteInvocationResult - */ - protected void writeRemoteInvocationResult( - HttpExchange exchange, RemoteInvocationResult result, OutputStream os) throws IOException { - - ObjectOutputStream oos = createObjectOutputStream(decorateOutputStream(exchange, os)); - doWriteRemoteInvocationResult(result, oos); - oos.flush(); - } - - /** - * Return the OutputStream to use for writing remote invocation results, - * potentially decorating the given original OutputStream. - *

The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param exchange current HTTP request/response - * @param os the original OutputStream - * @return the potentially decorated OutputStream - * @throws java.io.IOException in case of I/O failure - */ - protected OutputStream decorateOutputStream(HttpExchange exchange, OutputStream os) throws IOException { - return os; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/package-info.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/package-info.java deleted file mode 100644 index 8e26fd054..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/httpinvoker/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Remoting classes for transparent Java-to-Java remoting via HTTP invokers. - * Uses Java serialization just like RMI, but provides the same ease of setup - * as Caucho's HTTP-based Hessian and Burlap protocols. - * - *

HTTP invoker is the recommended protocol for Java-to-Java remoting. - * It is more powerful and more extensible than Hessian and Burlap, at the - * expense of being tied to Java. Neverthelesss, it is as easy to set up as - * Hessian and Burlap, which is its main advantage compared to RMI. - */ -package com.fr.third.springframework.remoting.httpinvoker; diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java deleted file mode 100644 index 81fffff4c..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.io.IOException; -import java.io.InputStream; -import java.rmi.server.RMIClassLoader; - -import com.fr.third.springframework.core.ConfigurableObjectInputStream; - -/** - * Special ObjectInputStream subclass that falls back to a specified codebase - * to load classes from if not found locally. In contrast to standard RMI - * conventions for dynamic class download, it is the client that determines - * the codebase URL here, rather than the "java.rmi.server.codebase" system - * property on the server. - * - *

Uses the JDK's RMIClassLoader to load classes from the specified codebase. - * The codebase can consist of multiple URLs, separated by spaces. - * Note that RMIClassLoader requires a SecurityManager to be set, like when - * using dynamic class download with standard RMI! (See the RMI documentation - * for details.) - * - *

Despite residing in the RMI package, this class is not used for - * RmiClientInterceptor, which uses the standard RMI infrastructure instead - * and thus is only able to rely on RMI's standard dynamic class download via - * "java.rmi.server.codebase". CodebaseAwareObjectInputStream is used by - * HttpInvokerClientInterceptor (see the "codebaseUrl" property there). - * - *

Thanks to Lionel Mestre for suggesting the option and providing - * a prototype! - * - * @author Juergen Hoeller - * @since 1.1.3 - * @see java.rmi.server.RMIClassLoader - * @see RemoteInvocationSerializingExporter#createObjectInputStream - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor#setCodebaseUrl - */ -public class CodebaseAwareObjectInputStream extends ConfigurableObjectInputStream { - - private final String codebaseUrl; - - - /** - * Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase. - * @param in the InputStream to read from - * @param codebaseUrl the codebase URL to load classes from if not found locally - * (can consist of multiple URLs, separated by spaces) - * @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream) - */ - public CodebaseAwareObjectInputStream(InputStream in, String codebaseUrl) throws IOException { - this(in, null, codebaseUrl); - } - - /** - * Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase. - * @param in the InputStream to read from - * @param classLoader the ClassLoader to use for loading local classes - * (may be {@code null} to indicate RMI's default ClassLoader) - * @param codebaseUrl the codebase URL to load classes from if not found locally - * (can consist of multiple URLs, separated by spaces) - * @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream) - */ - public CodebaseAwareObjectInputStream( - InputStream in, ClassLoader classLoader, String codebaseUrl) throws IOException { - - super(in, classLoader); - this.codebaseUrl = codebaseUrl; - } - - /** - * Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase. - * @param in the InputStream to read from - * @param classLoader the ClassLoader to use for loading local classes - * (may be {@code null} to indicate RMI's default ClassLoader) - * @param acceptProxyClasses whether to accept deserialization of proxy classes - * (may be deactivated as a security measure) - * @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream) - */ - public CodebaseAwareObjectInputStream( - InputStream in, ClassLoader classLoader, boolean acceptProxyClasses) throws IOException { - - super(in, classLoader, acceptProxyClasses); - this.codebaseUrl = null; - } - - - @Override - protected Class resolveFallbackIfPossible(String className, ClassNotFoundException ex) - throws IOException, ClassNotFoundException { - - // If codebaseUrl is set, try to load the class with the RMIClassLoader. - // Else, propagate the ClassNotFoundException. - if (this.codebaseUrl == null) { - throw ex; - } - return RMIClassLoader.loadClass(this.codebaseUrl, className); - } - - @Override - protected ClassLoader getFallbackClassLoader() throws IOException { - return RMIClassLoader.getClassLoader(this.codebaseUrl); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiClientInterceptor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiClientInterceptor.java deleted file mode 100644 index 4024fa9c4..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiClientInterceptor.java +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.rmi.RemoteException; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.rmi.PortableRemoteObject; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; -import org.omg.CORBA.OBJECT_NOT_EXIST; -import org.omg.CORBA.SystemException; - -import com.fr.third.springframework.aop.support.AopUtils; -import com.fr.third.springframework.beans.factory.InitializingBean; -import com.fr.third.springframework.jndi.JndiObjectLocator; -import com.fr.third.springframework.remoting.RemoteAccessException; -import com.fr.third.springframework.remoting.RemoteConnectFailureException; -import com.fr.third.springframework.remoting.RemoteInvocationFailureException; -import com.fr.third.springframework.remoting.RemoteLookupFailureException; -import com.fr.third.springframework.remoting.support.DefaultRemoteInvocationFactory; -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationFactory; -import com.fr.third.springframework.util.ReflectionUtils; - -/** - * {@link org.aopalliance.intercept.MethodInterceptor} for accessing RMI services - * from JNDI.Typically used for RMI-IIOP, but can also be used for EJB home objects - * (for example, a Stateful Session Bean home). In contrast to a plain JNDI lookup, - * this accessor also performs narrowing through PortableRemoteObject. - * - *

With conventional RMI services, this invoker is typically used with the RMI - * service interface. Alternatively, this invoker can also proxy a remote RMI service - * with a matching non-RMI business interface, i.e. an interface that mirrors the RMI - * service methods but does not declare RemoteExceptions. In the latter case, - * RemoteExceptions thrown by the RMI stub will automatically get converted to - * Spring's unchecked RemoteAccessException. - * - *

The JNDI environment can be specified as "jndiEnvironment" property, - * or be configured in a {@code jndi.properties} file or as system properties. - * For example: - * - *

<property name="jndiEnvironment">
- * 	 <props>
- *		 <prop key="java.naming.factory.initial">com.sun.jndi.cosnaming.CNCtxFactory</prop>
- *		 <prop key="java.naming.provider.url">iiop://localhost:1050</prop>
- *	 </props>
- * </property>
- * - * @author Juergen Hoeller - * @since 1.1 - * @see #setJndiTemplate - * @see #setJndiEnvironment - * @see #setJndiName - * @see JndiRmiServiceExporter - * @see JndiRmiProxyFactoryBean - * @see com.fr.third.springframework.remoting.RemoteAccessException - * @see java.rmi.RemoteException - * @see java.rmi.Remote - */ -public class JndiRmiClientInterceptor extends JndiObjectLocator implements MethodInterceptor, InitializingBean { - - // 定制 本类中注释掉的内容,见 - // https://code.fineres.com/projects/CORE/repos/base-third/commits/5b3f31597873b165b6a154393ee4ade942beec0a#fine-spring/src/com/fr/third/springframework/remoting/rmi/JndiRmiClientInterceptor.java - - private Class serviceInterface; - - private RemoteInvocationFactory remoteInvocationFactory = new DefaultRemoteInvocationFactory(); - - private boolean lookupStubOnStartup = true; - - private boolean cacheStub = true; - - private boolean refreshStubOnConnectFailure = false; - - private boolean exposeAccessContext = false; - - private Object cachedStub; - - private final Object stubMonitor = new Object(); - - - /** - * Set the interface of the service to access. - * The interface must be suitable for the particular service and remoting tool. - *

Typically required to be able to create a suitable service proxy, - * but can also be optional if the lookup returns a typed stub. - */ - public void setServiceInterface(Class serviceInterface) { - if (serviceInterface != null && !serviceInterface.isInterface()) { - throw new IllegalArgumentException("'serviceInterface' must be an interface"); - } - this.serviceInterface = serviceInterface; - } - - /** - * Return the interface of the service to access. - */ - public Class getServiceInterface() { - return this.serviceInterface; - } - - /** - * Set the RemoteInvocationFactory to use for this accessor. - * Default is a {@link DefaultRemoteInvocationFactory}. - *

A custom invocation factory can add further context information - * to the invocation, for example user credentials. - */ - public void setRemoteInvocationFactory(RemoteInvocationFactory remoteInvocationFactory) { - this.remoteInvocationFactory = remoteInvocationFactory; - } - - /** - * Return the RemoteInvocationFactory used by this accessor. - */ - public RemoteInvocationFactory getRemoteInvocationFactory() { - return this.remoteInvocationFactory; - } - - /** - * Set whether to look up the RMI stub on startup. Default is "true". - *

Can be turned off to allow for late start of the RMI server. - * In this case, the RMI stub will be fetched on first access. - * @see #setCacheStub - */ - public void setLookupStubOnStartup(boolean lookupStubOnStartup) { - this.lookupStubOnStartup = lookupStubOnStartup; - } - - /** - * Set whether to cache the RMI stub once it has been located. - * Default is "true". - *

Can be turned off to allow for hot restart of the RMI server. - * In this case, the RMI stub will be fetched for each invocation. - * @see #setLookupStubOnStartup - */ - public void setCacheStub(boolean cacheStub) { - this.cacheStub = cacheStub; - } - - /** - * Set whether to refresh the RMI stub on connect failure. - * Default is "false". - *

Can be turned on to allow for hot restart of the RMI server. - * If a cached RMI stub throws an RMI exception that indicates a - * remote connect failure, a fresh proxy will be fetched and the - * invocation will be retried. - * @see java.rmi.ConnectException - * @see java.rmi.ConnectIOException - * @see java.rmi.NoSuchObjectException - */ - public void setRefreshStubOnConnectFailure(boolean refreshStubOnConnectFailure) { - this.refreshStubOnConnectFailure = refreshStubOnConnectFailure; - } - - /** - * Set whether to expose the JNDI environment context for all access to the target - * RMI stub, i.e. for all method invocations on the exposed object reference. - *

Default is "false", i.e. to only expose the JNDI context for object lookup. - * Switch this flag to "true" in order to expose the JNDI environment (including - * the authorization context) for each RMI invocation, as needed by WebLogic - * for RMI stubs with authorization requirements. - */ - public void setExposeAccessContext(boolean exposeAccessContext) { - this.exposeAccessContext = exposeAccessContext; - } - - - @Override - public void afterPropertiesSet() throws NamingException { - super.afterPropertiesSet(); - prepare(); - } - - /** - * Fetches the RMI stub on startup, if necessary. - * @throws RemoteLookupFailureException if RMI stub creation failed - * @see #setLookupStubOnStartup - * @see #lookupStub - */ - public void prepare() throws RemoteLookupFailureException { - // Cache RMI stub on initialization? - if (this.lookupStubOnStartup) { - Object remoteObj = lookupStub(); - if (logger.isDebugEnabled()) { - if (remoteObj instanceof RmiInvocationHandler) { - logger.debug("JNDI RMI object [" + getJndiName() + "] is an RMI invoker"); - } - else if (getServiceInterface() != null) { - boolean isImpl = getServiceInterface().isInstance(remoteObj); - logger.debug("Using service interface [" + getServiceInterface().getName() + - "] for JNDI RMI object [" + getJndiName() + "] - " + - (!isImpl ? "not " : "") + "directly implemented"); - } - } - if (this.cacheStub) { - this.cachedStub = remoteObj; - } - } - } - - /** - * Create the RMI stub, typically by looking it up. - *

Called on interceptor initialization if "cacheStub" is "true"; - * else called for each invocation by {@link #getStub()}. - *

The default implementation retrieves the service from the - * JNDI environment. This can be overridden in subclasses. - * @return the RMI stub to store in this interceptor - * @throws RemoteLookupFailureException if RMI stub creation failed - * @see #setCacheStub - * @see #lookup - */ - protected Object lookupStub() throws RemoteLookupFailureException { - try { -// Object stub = lookup(); -// if (getServiceInterface() != null && !(stub instanceof RmiInvocationHandler)) { -// try { -// stub = PortableRemoteObject.narrow(stub, getServiceInterface()); -// } -// catch (ClassCastException ex) { -// throw new RemoteLookupFailureException( -// "Could not narrow RMI stub to service interface [" + getServiceInterface().getName() + "]", ex); -// } -// } - return lookup(); - } - catch (NamingException ex) { - throw new RemoteLookupFailureException("JNDI lookup for RMI service [" + getJndiName() + "] failed", ex); - } - } - - /** - * Return the RMI stub to use. Called for each invocation. - *

The default implementation returns the stub created on initialization, - * if any. Else, it invokes {@link #lookupStub} to get a new stub for - * each invocation. This can be overridden in subclasses, for example in - * order to cache a stub for a given amount of time before recreating it, - * or to test the stub whether it is still alive. - * @return the RMI stub to use for an invocation - * @throws NamingException if stub creation failed - * @throws RemoteLookupFailureException if RMI stub creation failed - */ - protected Object getStub() throws NamingException, RemoteLookupFailureException { - if (!this.cacheStub || (this.lookupStubOnStartup && !this.refreshStubOnConnectFailure)) { - return (this.cachedStub != null ? this.cachedStub : lookupStub()); - } - else { - synchronized (this.stubMonitor) { - if (this.cachedStub == null) { - this.cachedStub = lookupStub(); - } - return this.cachedStub; - } - } - } - - - /** - * Fetches an RMI stub and delegates to {@link #doInvoke}. - * If configured to refresh on connect failure, it will call - * {@link #refreshAndRetry} on corresponding RMI exceptions. - * @see #getStub - * @see #doInvoke - * @see #refreshAndRetry - * @see java.rmi.ConnectException - * @see java.rmi.ConnectIOException - * @see java.rmi.NoSuchObjectException - */ - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - Object stub; - try { - stub = getStub(); - } - catch (NamingException ex) { - throw new RemoteLookupFailureException("JNDI lookup for RMI service [" + getJndiName() + "] failed", ex); - } - - Context ctx = (this.exposeAccessContext ? getJndiTemplate().getContext() : null); - try { - return doInvoke(invocation, stub); - } - catch (RemoteConnectFailureException ex) { - return handleRemoteConnectFailure(invocation, ex); - } - catch (RemoteException ex) { - if (isConnectFailure(ex)) { - return handleRemoteConnectFailure(invocation, ex); - } - else { - throw ex; - } - } -// catch (SystemException ex) { -// if (isConnectFailure(ex)) { -// return handleRemoteConnectFailure(invocation, ex); -// } -// else { -// throw ex; -// } -// } - finally { - getJndiTemplate().releaseContext(ctx); - } - } - - /** - * Determine whether the given RMI exception indicates a connect failure. - *

The default implementation delegates to - * {@link RmiClientInterceptorUtils#isConnectFailure}. - * @param ex the RMI exception to check - * @return whether the exception should be treated as connect failure - */ - protected boolean isConnectFailure(RemoteException ex) { - return RmiClientInterceptorUtils.isConnectFailure(ex); - } - -// /** -// * Determine whether the given CORBA exception indicates a connect failure. -// *

The default implementation checks for CORBA's -// * {@link org.omg.CORBA.OBJECT_NOT_EXIST} exception. -// * @param ex the RMI exception to check -// * @return whether the exception should be treated as connect failure -// */ -// protected boolean isConnectFailure(SystemException ex) { -// return (ex instanceof OBJECT_NOT_EXIST); -// } - - /** - * Refresh the stub and retry the remote invocation if necessary. - *

If not configured to refresh on connect failure, this method - * simply rethrows the original exception. - * @param invocation the invocation that failed - * @param ex the exception raised on remote invocation - * @return the result value of the new invocation, if succeeded - * @throws Throwable an exception raised by the new invocation, if failed too. - */ - private Object handleRemoteConnectFailure(MethodInvocation invocation, Exception ex) throws Throwable { - if (this.refreshStubOnConnectFailure) { - if (logger.isDebugEnabled()) { - logger.debug("Could not connect to RMI service [" + getJndiName() + "] - retrying", ex); - } - else if (logger.isWarnEnabled()) { - logger.warn("Could not connect to RMI service [" + getJndiName() + "] - retrying"); - } - return refreshAndRetry(invocation); - } - else { - throw ex; - } - } - - /** - * Refresh the RMI stub and retry the given invocation. - * Called by invoke on connect failure. - * @param invocation the AOP method invocation - * @return the invocation result, if any - * @throws Throwable in case of invocation failure - * @see #invoke - */ - protected Object refreshAndRetry(MethodInvocation invocation) throws Throwable { - Object freshStub; - synchronized (this.stubMonitor) { - this.cachedStub = null; - freshStub = lookupStub(); - if (this.cacheStub) { - this.cachedStub = freshStub; - } - } - return doInvoke(invocation, freshStub); - } - - - /** - * Perform the given invocation on the given RMI stub. - * @param invocation the AOP method invocation - * @param stub the RMI stub to invoke - * @return the invocation result, if any - * @throws Throwable in case of invocation failure - */ - protected Object doInvoke(MethodInvocation invocation, Object stub) throws Throwable { - if (stub instanceof RmiInvocationHandler) { - // RMI invoker - try { - return doInvoke(invocation, (RmiInvocationHandler) stub); - } - catch (RemoteException ex) { - throw convertRmiAccessException(ex, invocation.getMethod()); - } -// catch (SystemException ex) { -// throw convertCorbaAccessException(ex, invocation.getMethod()); -// } - catch (InvocationTargetException ex) { - throw ex.getTargetException(); - } - catch (Throwable ex) { - throw new RemoteInvocationFailureException("Invocation of method [" + invocation.getMethod() + - "] failed in RMI service [" + getJndiName() + "]", ex); - } - } - else { - // traditional RMI stub - try { - return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, stub); - } - catch (InvocationTargetException ex) { - Throwable targetEx = ex.getTargetException(); - if (targetEx instanceof RemoteException) { - throw convertRmiAccessException((RemoteException) targetEx, invocation.getMethod()); - } -// else if (targetEx instanceof SystemException) { -// throw convertCorbaAccessException((SystemException) targetEx, invocation.getMethod()); -// } - else { - throw targetEx; - } - } - } - } - - /** - * Apply the given AOP method invocation to the given {@link RmiInvocationHandler}. - *

The default implementation delegates to {@link #createRemoteInvocation}. - * @param methodInvocation the current AOP method invocation - * @param invocationHandler the RmiInvocationHandler to apply the invocation to - * @return the invocation result - * @throws RemoteException in case of communication errors - * @throws NoSuchMethodException if the method name could not be resolved - * @throws IllegalAccessException if the method could not be accessed - * @throws InvocationTargetException if the method invocation resulted in an exception - * @see com.fr.third.springframework.remoting.support.RemoteInvocation - */ - protected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler) - throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - - if (AopUtils.isToStringMethod(methodInvocation.getMethod())) { - return "RMI invoker proxy for service URL [" + getJndiName() + "]"; - } - - return invocationHandler.invoke(createRemoteInvocation(methodInvocation)); - } - - /** - * Create a new RemoteInvocation object for the given AOP method invocation. - *

The default implementation delegates to the configured - * {@link #setRemoteInvocationFactory RemoteInvocationFactory}. - * This can be overridden in subclasses in order to provide custom RemoteInvocation - * subclasses, containing additional invocation parameters (e.g. user credentials). - *

Note that it is preferable to build a custom RemoteInvocationFactory - * as a reusable strategy, instead of overriding this method. - * @param methodInvocation the current AOP method invocation - * @return the RemoteInvocation object - * @see RemoteInvocationFactory#createRemoteInvocation - */ - protected RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { - return getRemoteInvocationFactory().createRemoteInvocation(methodInvocation); - } - - /** - * Convert the given RMI RemoteException that happened during remote access - * to Spring's RemoteAccessException if the method signature does not declare - * RemoteException. Else, return the original RemoteException. - * @param method the invoked method - * @param ex the RemoteException that happened - * @return the exception to be thrown to the caller - */ - private Exception convertRmiAccessException(RemoteException ex, Method method) { - return RmiClientInterceptorUtils.convertRmiAccessException(method, ex, isConnectFailure(ex), getJndiName()); - } - -// /** -// * Convert the given CORBA SystemException that happened during remote access -// * to Spring's RemoteAccessException if the method signature does not declare -// * RemoteException. Else, return the SystemException wrapped in a RemoteException. -// * @param method the invoked method -// * @param ex the RemoteException that happened -// * @return the exception to be thrown to the caller -// */ -// private Exception convertCorbaAccessException(SystemException ex, Method method) { -// if (ReflectionUtils.declaresException(method, RemoteException.class)) { -// // A traditional RMI service: wrap CORBA exceptions in standard RemoteExceptions. -// return new RemoteException("Failed to access CORBA service [" + getJndiName() + "]", ex); -// } -// else { -// if (isConnectFailure(ex)) { -// return new RemoteConnectFailureException("Could not connect to CORBA service [" + getJndiName() + "]", ex); -// } -// else { -// return new RemoteAccessException("Could not access CORBA service [" + getJndiName() + "]", ex); -// } -// } -// } -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java deleted file mode 100644 index 6a64fc716..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import javax.naming.NamingException; - -import com.fr.third.springframework.aop.framework.ProxyFactory; -import com.fr.third.springframework.beans.factory.BeanClassLoaderAware; -import com.fr.third.springframework.beans.factory.FactoryBean; -import com.fr.third.springframework.util.ClassUtils; - -/** - * {@link FactoryBean} for RMI proxies from JNDI. - * - *

Typically used for RMI-IIOP (CORBA), but can also be used for EJB home objects - * (for example, a Stateful Session Bean home). In contrast to a plain JNDI lookup, - * this accessor also performs narrowing through {@link javax.rmi.PortableRemoteObject}. - * - *

With conventional RMI services, this invoker is typically used with the RMI - * service interface. Alternatively, this invoker can also proxy a remote RMI service - * with a matching non-RMI business interface, i.e. an interface that mirrors the RMI - * service methods but does not declare RemoteExceptions. In the latter case, - * RemoteExceptions thrown by the RMI stub will automatically get converted to - * Spring's unchecked RemoteAccessException. - * - *

The JNDI environment can be specified as "jndiEnvironment" property, - * or be configured in a {@code jndi.properties} file or as system properties. - * For example: - * - *

<property name="jndiEnvironment">
- * 	 <props>
- *		 <prop key="java.naming.factory.initial">com.sun.jndi.cosnaming.CNCtxFactory</prop>
- *		 <prop key="java.naming.provider.url">iiop://localhost:1050</prop>
- *	 </props>
- * </property>
- * - * @author Juergen Hoeller - * @since 1.1 - * @see #setServiceInterface - * @see #setJndiName - * @see #setJndiTemplate - * @see #setJndiEnvironment - * @see #setJndiName - * @see JndiRmiServiceExporter - * @see com.fr.third.springframework.remoting.RemoteAccessException - * @see java.rmi.RemoteException - * @see java.rmi.Remote - * @see javax.rmi.PortableRemoteObject#narrow - */ -public class JndiRmiProxyFactoryBean extends JndiRmiClientInterceptor - implements FactoryBean, BeanClassLoaderAware { - - private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); - - private Object serviceProxy; - - - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.beanClassLoader = classLoader; - } - - @Override - public void afterPropertiesSet() throws NamingException { - super.afterPropertiesSet(); - if (getServiceInterface() == null) { - throw new IllegalArgumentException("Property 'serviceInterface' is required"); - } - this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(this.beanClassLoader); - } - - - @Override - public Object getObject() { - return this.serviceProxy; - } - - @Override - public Class getObjectType() { - return getServiceInterface(); - } - - @Override - public boolean isSingleton() { - return true; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiServiceExporter.java deleted file mode 100644 index 7176263af..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/JndiRmiServiceExporter.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.rmi.NoSuchObjectException; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.util.Properties; -import javax.naming.NamingException; - -import com.fr.third.springframework.beans.factory.DisposableBean; -import com.fr.third.springframework.beans.factory.InitializingBean; -import com.fr.third.springframework.jndi.JndiTemplate; - -/** - * Service exporter which binds RMI services to JNDI. - * Typically used for RMI-IIOP (CORBA). - * - * You need to run "rmic" with the "-iiop" option to generate corresponding - * stubs and skeletons for each exported service. - * - *

Also supports exposing any non-RMI service via RMI invokers, to be accessed - * via {@link JndiRmiClientInterceptor} / {@link JndiRmiProxyFactoryBean}'s - * automatic detection of such invokers. - * - *

With an RMI invoker, RMI communication works on the {@link RmiInvocationHandler} - * level, needing only one stub for any service. Service interfaces do not have to - * extend {@code java.rmi.Remote} or throw {@code java.rmi.RemoteException} - * on all methods, but in and out parameters have to be serializable. - * - *

The JNDI environment can be specified as "jndiEnvironment" bean property, - * or be configured in a {@code jndi.properties} file or as system properties. - * For example: - * - *

<property name="jndiEnvironment">
- * 	 <props>
- *		 <prop key="java.naming.factory.initial">com.sun.jndi.cosnaming.CNCtxFactory</prop>
- *		 <prop key="java.naming.provider.url">iiop://localhost:1050</prop>
- *	 </props>
- * </property>
- * - * @author Juergen Hoeller - * @since 1.1 - * @see #setService - * @see #setJndiTemplate - * @see #setJndiEnvironment - * @see #setJndiName - * @see JndiRmiClientInterceptor - * @see JndiRmiProxyFactoryBean - */ -public class JndiRmiServiceExporter extends RmiBasedExporter implements InitializingBean, DisposableBean { - - // 定制 本类中注释掉的内容,见 - // https://code.fineres.com/projects/CORE/repos/base-third/commits/5b3f31597873b165b6a154393ee4ade942beec0a#fine-spring/src/com/fr/third/springframework/remoting/rmi/JndiRmiClientInterceptor.java - - private JndiTemplate jndiTemplate = new JndiTemplate(); - - private String jndiName; - - private Remote exportedObject; - - - /** - * Set the JNDI template to use for JNDI lookups. - * You can also specify JNDI environment settings via "jndiEnvironment". - * @see #setJndiEnvironment - */ - public void setJndiTemplate(JndiTemplate jndiTemplate) { - this.jndiTemplate = (jndiTemplate != null ? jndiTemplate : new JndiTemplate()); - } - - /** - * Set the JNDI environment to use for JNDI lookups. - * Creates a JndiTemplate with the given environment settings. - * @see #setJndiTemplate - */ - public void setJndiEnvironment(Properties jndiEnvironment) { - this.jndiTemplate = new JndiTemplate(jndiEnvironment); - } - - /** - * Set the JNDI name of the exported RMI service. - */ - public void setJndiName(String jndiName) { - this.jndiName = jndiName; - } - - - @Override - public void afterPropertiesSet() throws NamingException, RemoteException { - prepare(); - } - - /** - * Initialize this service exporter, binding the specified service to JNDI. - * @throws NamingException if service binding failed - * @throws RemoteException if service export failed - */ - public void prepare() throws NamingException, RemoteException { - if (this.jndiName == null) { - throw new IllegalArgumentException("Property 'jndiName' is required"); - } - - // Initialize and cache exported object. - this.exportedObject = getObjectToExport(); -// PortableRemoteObject.exportObject(this.exportedObject); - - rebind(); - } - - /** - * Rebind the specified service to JNDI, for recovering in case - * of the target registry having been restarted. - * @throws NamingException if service binding failed - */ - public void rebind() throws NamingException { - if (logger.isInfoEnabled()) { - logger.info("Binding RMI service to JNDI location [" + this.jndiName + "]"); - } - this.jndiTemplate.rebind(this.jndiName, this.exportedObject); - } - - /** - * Unbind the RMI service from JNDI on bean factory shutdown. - */ - @Override - public void destroy() throws NamingException, NoSuchObjectException { - if (logger.isInfoEnabled()) { - logger.info("Unbinding RMI service from JNDI location [" + this.jndiName + "]"); - } - this.jndiTemplate.unbind(this.jndiName); -// PortableRemoteObject.unexportObject(this.exportedObject); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java deleted file mode 100644 index 9f227cfba..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.rmi.RemoteException; - -import com.fr.third.springframework.beans.factory.InitializingBean; -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationBasedExporter; -import com.fr.third.springframework.remoting.support.RemoteInvocationResult; -import com.fr.third.springframework.util.Assert; -import com.fr.third.springframework.util.ClassUtils; - -/** - * Abstract base class for remote service exporters that explicitly deserialize - * {@link com.fr.third.springframework.remoting.support.RemoteInvocation} objects and serialize - * {@link com.fr.third.springframework.remoting.support.RemoteInvocationResult} objects, - * for example Spring's HTTP invoker. - * - *

Provides template methods for {@code ObjectInputStream} and - * {@code ObjectOutputStream} handling. - * - * @author Juergen Hoeller - * @since 2.5.1 - * @see java.io.ObjectInputStream - * @see java.io.ObjectOutputStream - * @see #doReadRemoteInvocation - * @see #doWriteRemoteInvocationResult - */ -public abstract class RemoteInvocationSerializingExporter extends RemoteInvocationBasedExporter - implements InitializingBean { - - /** - * Default content type: "application/x-java-serialized-object" - */ - public static final String CONTENT_TYPE_SERIALIZED_OBJECT = "application/x-java-serialized-object"; - - - private String contentType = CONTENT_TYPE_SERIALIZED_OBJECT; - - private boolean acceptProxyClasses = true; - - private Object proxy; - - - /** - * Specify the content type to use for sending remote invocation responses. - *

Default is "application/x-java-serialized-object". - */ - public void setContentType(String contentType) { - Assert.notNull(contentType, "'contentType' must not be null"); - this.contentType = contentType; - } - - /** - * Return the content type to use for sending remote invocation responses. - */ - public String getContentType() { - return this.contentType; - } - - /** - * Set whether to accept deserialization of proxy classes. - *

Default is "true". May be deactivated as a security measure. - */ - public void setAcceptProxyClasses(boolean acceptProxyClasses) { - this.acceptProxyClasses = acceptProxyClasses; - } - - /** - * Return whether to accept deserialization of proxy classes. - */ - public boolean isAcceptProxyClasses() { - return this.acceptProxyClasses; - } - - - @Override - public void afterPropertiesSet() { - prepare(); - } - - /** - * Initialize this service exporter. - */ - public void prepare() { - this.proxy = getProxyForService(); - } - - protected final Object getProxy() { - if (this.proxy == null) { - throw new IllegalStateException(ClassUtils.getShortName(getClass()) + " has not been initialized"); - } - return this.proxy; - } - - - /** - * Create an ObjectInputStream for the given InputStream. - *

The default implementation creates a Spring {@link CodebaseAwareObjectInputStream}. - * @param is the InputStream to read from - * @return the new ObjectInputStream instance to use - * @throws java.io.IOException if creation of the ObjectInputStream failed - */ - protected ObjectInputStream createObjectInputStream(InputStream is) throws IOException { - return new CodebaseAwareObjectInputStream(is, getBeanClassLoader(), isAcceptProxyClasses()); - } - - /** - * Perform the actual reading of an invocation result object from the - * given ObjectInputStream. - *

The default implementation simply calls - * {@link java.io.ObjectInputStream#readObject()}. - * Can be overridden for deserialization of a custom wrapper object rather - * than the plain invocation, for example an encryption-aware holder. - * @param ois the ObjectInputStream to read from - * @return the RemoteInvocationResult object - * @throws java.io.IOException in case of I/O failure - * @throws ClassNotFoundException if case of a transferred class not - * being found in the local ClassLoader - */ - protected RemoteInvocation doReadRemoteInvocation(ObjectInputStream ois) - throws IOException, ClassNotFoundException { - - Object obj = ois.readObject(); - if (!(obj instanceof RemoteInvocation)) { - throw new RemoteException("Deserialized object needs to be assignable to type [" + - RemoteInvocation.class.getName() + "]: " + ClassUtils.getDescriptiveType(obj)); - } - return (RemoteInvocation) obj; - } - - /** - * Create an ObjectOutputStream for the given OutputStream. - *

The default implementation creates a plain - * {@link java.io.ObjectOutputStream}. - * @param os the OutputStream to write to - * @return the new ObjectOutputStream instance to use - * @throws java.io.IOException if creation of the ObjectOutputStream failed - */ - protected ObjectOutputStream createObjectOutputStream(OutputStream os) throws IOException { - return new ObjectOutputStream(os); - } - - /** - * Perform the actual writing of the given invocation result object - * to the given ObjectOutputStream. - *

The default implementation simply calls - * {@link java.io.ObjectOutputStream#writeObject}. - * Can be overridden for serialization of a custom wrapper object rather - * than the plain invocation, for example an encryption-aware holder. - * @param result the RemoteInvocationResult object - * @param oos the ObjectOutputStream to write to - * @throws java.io.IOException if thrown by I/O methods - */ - protected void doWriteRemoteInvocationResult(RemoteInvocationResult result, ObjectOutputStream oos) - throws IOException { - - oos.writeObject(result); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiBasedExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiBasedExporter.java deleted file mode 100644 index 7ab9774b8..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiBasedExporter.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.lang.reflect.InvocationTargetException; -import java.rmi.Remote; - -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.remoting.support.RemoteInvocationBasedExporter; - -/** - * Convenient superclass for RMI-based remote exporters. Provides a facility - * to automatically wrap a given plain Java service object with an - * RmiInvocationWrapper, exposing the {@link RmiInvocationHandler} remote interface. - * - *

Using the RMI invoker mechanism, RMI communication operates at the {@link RmiInvocationHandler} - * level, sharing a common invoker stub for any number of services. Service interfaces are not - * required to extend {@code java.rmi.Remote} or declare {@code java.rmi.RemoteException} - * on all service methods. However, in and out parameters still have to be serializable. - * - * @author Juergen Hoeller - * @since 1.2.5 - * @see RmiServiceExporter - * @see JndiRmiServiceExporter - */ -public abstract class RmiBasedExporter extends RemoteInvocationBasedExporter { - - /** - * Determine the object to export: either the service object itself - * or a RmiInvocationWrapper in case of a non-RMI service object. - * @return the RMI object to export - * @see #setService - * @see #setServiceInterface - */ - protected Remote getObjectToExport() { - // determine remote object - if (getService() instanceof Remote && - (getServiceInterface() == null || Remote.class.isAssignableFrom(getServiceInterface()))) { - // conventional RMI service - return (Remote) getService(); - } - else { - // RMI invoker - if (logger.isDebugEnabled()) { - logger.debug("RMI service [" + getService() + "] is an RMI invoker"); - } - return new RmiInvocationWrapper(getProxyForService(), this); - } - } - - /** - * Redefined here to be visible to RmiInvocationWrapper. - * Simply delegates to the corresponding superclass method. - */ - @Override - protected Object invoke(RemoteInvocation invocation, Object targetObject) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - - return super.invoke(invocation, targetObject); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptor.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptor.java deleted file mode 100644 index 9094c5608..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptor.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.rmi.Naming; -import java.rmi.NotBoundException; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMIClientSocketFactory; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -import com.fr.third.springframework.aop.support.AopUtils; -import com.fr.third.springframework.remoting.RemoteConnectFailureException; -import com.fr.third.springframework.remoting.RemoteInvocationFailureException; -import com.fr.third.springframework.remoting.RemoteLookupFailureException; -import com.fr.third.springframework.remoting.support.RemoteInvocationBasedAccessor; -import com.fr.third.springframework.remoting.support.RemoteInvocationUtils; - -/** - * {@link org.aopalliance.intercept.MethodInterceptor} for accessing conventional - * RMI services or RMI invokers. The service URL must be a valid RMI URL - * (e.g. "rmi://localhost:1099/myservice"). - * - *

RMI invokers work at the RmiInvocationHandler level, needing only one stub for - * any service. Service interfaces do not have to extend {@code java.rmi.Remote} - * or throw {@code java.rmi.RemoteException}. Spring's unchecked - * RemoteAccessException will be thrown on remote invocation failure. - * Of course, in and out parameters have to be serializable. - * - *

With conventional RMI services, this invoker is typically used with the RMI - * service interface. Alternatively, this invoker can also proxy a remote RMI service - * with a matching non-RMI business interface, i.e. an interface that mirrors the RMI - * service methods but does not declare RemoteExceptions. In the latter case, - * RemoteExceptions thrown by the RMI stub will automatically get converted to - * Spring's unchecked RemoteAccessException. - * - * @author Juergen Hoeller - * @since 29.09.2003 - * @see RmiServiceExporter - * @see RmiProxyFactoryBean - * @see RmiInvocationHandler - * @see com.fr.third.springframework.remoting.RemoteAccessException - * @see java.rmi.RemoteException - * @see java.rmi.Remote - */ -public class RmiClientInterceptor extends RemoteInvocationBasedAccessor - implements MethodInterceptor { - - private boolean lookupStubOnStartup = true; - - private boolean cacheStub = true; - - private boolean refreshStubOnConnectFailure = false; - - private RMIClientSocketFactory registryClientSocketFactory; - - private Remote cachedStub; - - private final Object stubMonitor = new Object(); - - - /** - * Set whether to look up the RMI stub on startup. Default is "true". - *

Can be turned off to allow for late start of the RMI server. - * In this case, the RMI stub will be fetched on first access. - * @see #setCacheStub - */ - public void setLookupStubOnStartup(boolean lookupStubOnStartup) { - this.lookupStubOnStartup = lookupStubOnStartup; - } - - /** - * Set whether to cache the RMI stub once it has been located. - * Default is "true". - *

Can be turned off to allow for hot restart of the RMI server. - * In this case, the RMI stub will be fetched for each invocation. - * @see #setLookupStubOnStartup - */ - public void setCacheStub(boolean cacheStub) { - this.cacheStub = cacheStub; - } - - /** - * Set whether to refresh the RMI stub on connect failure. - * Default is "false". - *

Can be turned on to allow for hot restart of the RMI server. - * If a cached RMI stub throws an RMI exception that indicates a - * remote connect failure, a fresh proxy will be fetched and the - * invocation will be retried. - * @see java.rmi.ConnectException - * @see java.rmi.ConnectIOException - * @see java.rmi.NoSuchObjectException - */ - public void setRefreshStubOnConnectFailure(boolean refreshStubOnConnectFailure) { - this.refreshStubOnConnectFailure = refreshStubOnConnectFailure; - } - - /** - * Set a custom RMI client socket factory to use for accessing the RMI registry. - * @see java.rmi.server.RMIClientSocketFactory - * @see java.rmi.registry.LocateRegistry#getRegistry(String, int, RMIClientSocketFactory) - */ - public void setRegistryClientSocketFactory(RMIClientSocketFactory registryClientSocketFactory) { - this.registryClientSocketFactory = registryClientSocketFactory; - } - - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - prepare(); - } - - /** - * Fetches RMI stub on startup, if necessary. - * @throws RemoteLookupFailureException if RMI stub creation failed - * @see #setLookupStubOnStartup - * @see #lookupStub - */ - public void prepare() throws RemoteLookupFailureException { - // Cache RMI stub on initialization? - if (this.lookupStubOnStartup) { - Remote remoteObj = lookupStub(); - if (logger.isDebugEnabled()) { - if (remoteObj instanceof RmiInvocationHandler) { - logger.debug("RMI stub [" + getServiceUrl() + "] is an RMI invoker"); - } - else if (getServiceInterface() != null) { - boolean isImpl = getServiceInterface().isInstance(remoteObj); - logger.debug("Using service interface [" + getServiceInterface().getName() + - "] for RMI stub [" + getServiceUrl() + "] - " + - (!isImpl ? "not " : "") + "directly implemented"); - } - } - if (this.cacheStub) { - this.cachedStub = remoteObj; - } - } - } - - /** - * Create the RMI stub, typically by looking it up. - *

Called on interceptor initialization if "cacheStub" is "true"; - * else called for each invocation by {@link #getStub()}. - *

The default implementation looks up the service URL via - * {@code java.rmi.Naming}. This can be overridden in subclasses. - * @return the RMI stub to store in this interceptor - * @throws RemoteLookupFailureException if RMI stub creation failed - * @see #setCacheStub - * @see java.rmi.Naming#lookup - */ - protected Remote lookupStub() throws RemoteLookupFailureException { - try { - Remote stub = null; - if (this.registryClientSocketFactory != null) { - // RMIClientSocketFactory specified for registry access. - // Unfortunately, due to RMI API limitations, this means - // that we need to parse the RMI URL ourselves and perform - // straight LocateRegistry.getRegistry/Registry.lookup calls. - URL url = new URL(null, getServiceUrl(), new DummyURLStreamHandler()); - String protocol = url.getProtocol(); - if (protocol != null && !"rmi".equals(protocol)) { - throw new MalformedURLException("Invalid URL scheme '" + protocol + "'"); - } - String host = url.getHost(); - int port = url.getPort(); - String name = url.getPath(); - if (name != null && name.startsWith("/")) { - name = name.substring(1); - } - Registry registry = LocateRegistry.getRegistry(host, port, this.registryClientSocketFactory); - stub = registry.lookup(name); - } - else { - // Can proceed with standard RMI lookup API... - stub = Naming.lookup(getServiceUrl()); - } - if (logger.isDebugEnabled()) { - logger.debug("Located RMI stub with URL [" + getServiceUrl() + "]"); - } - return stub; - } - catch (MalformedURLException ex) { - throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex); - } - catch (NotBoundException ex) { - throw new RemoteLookupFailureException( - "Could not find RMI service [" + getServiceUrl() + "] in RMI registry", ex); - } - catch (RemoteException ex) { - throw new RemoteLookupFailureException("Lookup of RMI stub failed", ex); - } - } - - /** - * Return the RMI stub to use. Called for each invocation. - *

The default implementation returns the stub created on initialization, - * if any. Else, it invokes {@link #lookupStub} to get a new stub for - * each invocation. This can be overridden in subclasses, for example in - * order to cache a stub for a given amount of time before recreating it, - * or to test the stub whether it is still alive. - * @return the RMI stub to use for an invocation - * @throws RemoteLookupFailureException if RMI stub creation failed - * @see #lookupStub - */ - protected Remote getStub() throws RemoteLookupFailureException { - if (!this.cacheStub || (this.lookupStubOnStartup && !this.refreshStubOnConnectFailure)) { - return (this.cachedStub != null ? this.cachedStub : lookupStub()); - } - else { - synchronized (this.stubMonitor) { - if (this.cachedStub == null) { - this.cachedStub = lookupStub(); - } - return this.cachedStub; - } - } - } - - - /** - * Fetches an RMI stub and delegates to {@code doInvoke}. - * If configured to refresh on connect failure, it will call - * {@link #refreshAndRetry} on corresponding RMI exceptions. - * @see #getStub - * @see #doInvoke(MethodInvocation, Remote) - * @see #refreshAndRetry - * @see java.rmi.ConnectException - * @see java.rmi.ConnectIOException - * @see java.rmi.NoSuchObjectException - */ - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - Remote stub = getStub(); - try { - return doInvoke(invocation, stub); - } - catch (RemoteConnectFailureException ex) { - return handleRemoteConnectFailure(invocation, ex); - } - catch (RemoteException ex) { - if (isConnectFailure(ex)) { - return handleRemoteConnectFailure(invocation, ex); - } - else { - throw ex; - } - } - } - - /** - * Determine whether the given RMI exception indicates a connect failure. - *

The default implementation delegates to - * {@link RmiClientInterceptorUtils#isConnectFailure}. - * @param ex the RMI exception to check - * @return whether the exception should be treated as connect failure - */ - protected boolean isConnectFailure(RemoteException ex) { - return RmiClientInterceptorUtils.isConnectFailure(ex); - } - - /** - * Refresh the stub and retry the remote invocation if necessary. - *

If not configured to refresh on connect failure, this method - * simply rethrows the original exception. - * @param invocation the invocation that failed - * @param ex the exception raised on remote invocation - * @return the result value of the new invocation, if succeeded - * @throws Throwable an exception raised by the new invocation, - * if it failed as well - * @see #setRefreshStubOnConnectFailure - * @see #doInvoke - */ - private Object handleRemoteConnectFailure(MethodInvocation invocation, Exception ex) throws Throwable { - if (this.refreshStubOnConnectFailure) { - String msg = "Could not connect to RMI service [" + getServiceUrl() + "] - retrying"; - if (logger.isDebugEnabled()) { - logger.warn(msg, ex); - } - else if (logger.isWarnEnabled()) { - logger.warn(msg); - } - return refreshAndRetry(invocation); - } - else { - throw ex; - } - } - - /** - * Refresh the RMI stub and retry the given invocation. - * Called by invoke on connect failure. - * @param invocation the AOP method invocation - * @return the invocation result, if any - * @throws Throwable in case of invocation failure - * @see #invoke - */ - protected Object refreshAndRetry(MethodInvocation invocation) throws Throwable { - Remote freshStub = null; - synchronized (this.stubMonitor) { - this.cachedStub = null; - freshStub = lookupStub(); - if (this.cacheStub) { - this.cachedStub = freshStub; - } - } - return doInvoke(invocation, freshStub); - } - - /** - * Perform the given invocation on the given RMI stub. - * @param invocation the AOP method invocation - * @param stub the RMI stub to invoke - * @return the invocation result, if any - * @throws Throwable in case of invocation failure - */ - protected Object doInvoke(MethodInvocation invocation, Remote stub) throws Throwable { - if (stub instanceof RmiInvocationHandler) { - // RMI invoker - try { - return doInvoke(invocation, (RmiInvocationHandler) stub); - } - catch (RemoteException ex) { - throw RmiClientInterceptorUtils.convertRmiAccessException( - invocation.getMethod(), ex, isConnectFailure(ex), getServiceUrl()); - } - catch (InvocationTargetException ex) { - Throwable exToThrow = ex.getTargetException(); - RemoteInvocationUtils.fillInClientStackTraceIfPossible(exToThrow); - throw exToThrow; - } - catch (Throwable ex) { - throw new RemoteInvocationFailureException("Invocation of method [" + invocation.getMethod() + - "] failed in RMI service [" + getServiceUrl() + "]", ex); - } - } - else { - // traditional RMI stub - try { - return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, stub); - } - catch (InvocationTargetException ex) { - Throwable targetEx = ex.getTargetException(); - if (targetEx instanceof RemoteException) { - RemoteException rex = (RemoteException) targetEx; - throw RmiClientInterceptorUtils.convertRmiAccessException( - invocation.getMethod(), rex, isConnectFailure(rex), getServiceUrl()); - } - else { - throw targetEx; - } - } - } - } - - /** - * Apply the given AOP method invocation to the given {@link RmiInvocationHandler}. - *

The default implementation delegates to {@link #createRemoteInvocation}. - * @param methodInvocation the current AOP method invocation - * @param invocationHandler the RmiInvocationHandler to apply the invocation to - * @return the invocation result - * @throws RemoteException in case of communication errors - * @throws NoSuchMethodException if the method name could not be resolved - * @throws IllegalAccessException if the method could not be accessed - * @throws InvocationTargetException if the method invocation resulted in an exception - * @see com.fr.third.springframework.remoting.support.RemoteInvocation - */ - protected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler) - throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - - if (AopUtils.isToStringMethod(methodInvocation.getMethod())) { - return "RMI invoker proxy for service URL [" + getServiceUrl() + "]"; - } - - return invocationHandler.invoke(createRemoteInvocation(methodInvocation)); - } - - - /** - * Dummy URLStreamHandler that's just specified to suppress the standard - * {@code java.net.URL} URLStreamHandler lookup, to be able to - * use the standard URL class for parsing "rmi:..." URLs. - */ - private static class DummyURLStreamHandler extends URLStreamHandler { - - @Override - protected URLConnection openConnection(URL url) throws IOException { - throw new UnsupportedOperationException(); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptorUtils.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptorUtils.java deleted file mode 100644 index ae2fb4e32..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiClientInterceptorUtils.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.SocketException; -import java.rmi.ConnectException; -import java.rmi.ConnectIOException; -import java.rmi.NoSuchObjectException; -import java.rmi.RemoteException; -import java.rmi.StubNotFoundException; -import java.rmi.UnknownHostException; - -import org.aopalliance.intercept.MethodInvocation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.fr.third.springframework.remoting.RemoteAccessException; -import com.fr.third.springframework.remoting.RemoteConnectFailureException; -import com.fr.third.springframework.remoting.RemoteProxyFailureException; -import com.fr.third.springframework.util.ReflectionUtils; - -/** - * Factored-out methods for performing invocations within an RMI client. - * Can handle both RMI and non-RMI service interfaces working on an RMI stub. - * - *

Note: This is an SPI class, not intended to be used by applications. - * - * @author Juergen Hoeller - * @since 1.1 - */ -public abstract class RmiClientInterceptorUtils { - - // 定制 本类中注释掉的内容,见 - // https://code.fineres.com/projects/CORE/repos/base-third/commits/5b3f31597873b165b6a154393ee4ade942beec0a#fine-spring/src/com/fr/third/springframework/remoting/rmi/JndiRmiClientInterceptor.java - - private static final Log logger = LogFactory.getLog(RmiClientInterceptorUtils.class); - - - /** - * Perform a raw method invocation on the given RMI stub, - * letting reflection exceptions through as-is. - * @param invocation the AOP MethodInvocation - * @param stub the RMI stub - * @return the invocation result, if any - * @throws InvocationTargetException if thrown by reflection - */ - public static Object invokeRemoteMethod(MethodInvocation invocation, Object stub) - throws InvocationTargetException { - - Method method = invocation.getMethod(); - try { - if (method.getDeclaringClass().isInstance(stub)) { - // directly implemented - return method.invoke(stub, invocation.getArguments()); - } - else { - // not directly implemented - Method stubMethod = stub.getClass().getMethod(method.getName(), method.getParameterTypes()); - return stubMethod.invoke(stub, invocation.getArguments()); - } - } - catch (InvocationTargetException ex) { - throw ex; - } - catch (NoSuchMethodException ex) { - throw new RemoteProxyFailureException("No matching RMI stub method found for: " + method, ex); - } - catch (Throwable ex) { - throw new RemoteProxyFailureException("Invocation of RMI stub method failed: " + method, ex); - } - } - - /** - * Wrap the given arbitrary exception that happened during remote access - * in either a RemoteException or a Spring RemoteAccessException (if the - * method signature does not support RemoteException). - *

Only call this for remote access exceptions, not for exceptions - * thrown by the target service itself! - * @param method the invoked method - * @param ex the exception that happened, to be used as cause for the - * RemoteAccessException or RemoteException - * @param message the message for the RemoteAccessException respectively - * RemoteException - * @return the exception to be thrown to the caller - */ - public static Exception convertRmiAccessException(Method method, Throwable ex, String message) { - if (logger.isDebugEnabled()) { - logger.debug(message, ex); - } - if (ReflectionUtils.declaresException(method, RemoteException.class)) { - return new RemoteException(message, ex); - } - else { - return new RemoteAccessException(message, ex); - } - } - - /** - * Convert the given RemoteException that happened during remote access - * to Spring's RemoteAccessException if the method signature does not - * support RemoteException. Else, return the original RemoteException. - * @param method the invoked method - * @param ex the RemoteException that happened - * @param serviceName the name of the service (for debugging purposes) - * @return the exception to be thrown to the caller - */ - public static Exception convertRmiAccessException(Method method, RemoteException ex, String serviceName) { - return convertRmiAccessException(method, ex, isConnectFailure(ex), serviceName); - } - - /** - * Convert the given RemoteException that happened during remote access - * to Spring's RemoteAccessException if the method signature does not - * support RemoteException. Else, return the original RemoteException. - * @param method the invoked method - * @param ex the RemoteException that happened - * @param isConnectFailure whether the given exception should be considered - * a connect failure - * @param serviceName the name of the service (for debugging purposes) - * @return the exception to be thrown to the caller - */ - public static Exception convertRmiAccessException( - Method method, RemoteException ex, boolean isConnectFailure, String serviceName) { - - if (logger.isDebugEnabled()) { - logger.debug("Remote service [" + serviceName + "] threw exception", ex); - } - if (ReflectionUtils.declaresException(method, ex.getClass())) { - return ex; - } - else { - if (isConnectFailure) { - return new RemoteConnectFailureException("Could not connect to remote service [" + serviceName + "]", ex); - } - else { - return new RemoteAccessException("Could not access remote service [" + serviceName + "]", ex); - } - } - } - - /** - * Determine whether the given RMI exception indicates a connect failure. - *

Treats RMI's ConnectException, ConnectIOException, UnknownHostException, - * NoSuchObjectException and StubNotFoundException as connect failure. - * @param ex the RMI exception to check - * @return whether the exception should be treated as connect failure - * @see java.rmi.ConnectException - * @see java.rmi.ConnectIOException - * @see java.rmi.UnknownHostException - * @see java.rmi.NoSuchObjectException - * @see java.rmi.StubNotFoundException - */ - public static boolean isConnectFailure(RemoteException ex) { - return (ex instanceof ConnectException || ex instanceof ConnectIOException || - ex instanceof UnknownHostException || ex instanceof NoSuchObjectException || - ex instanceof StubNotFoundException || ex.getCause() instanceof SocketException || - isCorbaConnectFailure(ex.getCause())); - } - - /** - * Check whether the given RMI exception root cause indicates a CORBA - * connection failure. - *

This is relevant on the IBM JVM, in particular for WebSphere EJB clients. - *

See the - * IBM website - * for details. - * @param ex the RMI exception to check - */ - private static boolean isCorbaConnectFailure(Throwable ex) { -// return ((ex instanceof COMM_FAILURE || ex instanceof NO_RESPONSE) && -// ((SystemException) ex).completed == CompletionStatus.COMPLETED_NO); - return (ex instanceof ConnectException || ex instanceof ConnectIOException || - ex instanceof UnknownHostException || ex instanceof NoSuchObjectException || - ex instanceof StubNotFoundException || ex.getCause() instanceof SocketException); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationHandler.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationHandler.java deleted file mode 100644 index 6a75c57f3..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.lang.reflect.InvocationTargetException; -import java.rmi.Remote; -import java.rmi.RemoteException; - -import com.fr.third.springframework.remoting.support.RemoteInvocation; - -/** - * Interface for RMI invocation handlers instances on the server, - * wrapping exported services. A client uses a stub implementing - * this interface to access such a service. - * - *

This is an SPI interface, not to be used directly by applications. - * - * @author Juergen Hoeller - * @since 14.05.2003 - */ -public interface RmiInvocationHandler extends Remote { - - /** - * Return the name of the target interface that this invoker operates on. - * @return the name of the target interface, or {@code null} if none - * @throws RemoteException in case of communication errors - * @see RmiServiceExporter#getServiceInterface() - */ - public String getTargetInterfaceName() throws RemoteException; - - /** - * Apply the given invocation to the target object. - *

Called by - * {@link RmiClientInterceptor#doInvoke(org.aopalliance.intercept.MethodInvocation, RmiInvocationHandler)}. - * @param invocation object that encapsulates invocation parameters - * @return the object returned from the invoked method, if any - * @throws RemoteException in case of communication errors - * @throws NoSuchMethodException if the method name could not be resolved - * @throws IllegalAccessException if the method could not be accessed - * @throws InvocationTargetException if the method invocation resulted in an exception - */ - public Object invoke(RemoteInvocation invocation) - throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException; - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationWrapper.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationWrapper.java deleted file mode 100644 index 65289b644..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiInvocationWrapper.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.lang.reflect.InvocationTargetException; -import java.rmi.RemoteException; - -import com.fr.third.springframework.remoting.support.RemoteInvocation; -import com.fr.third.springframework.util.Assert; - -/** - * Server-side implementation of {@link RmiInvocationHandler}. An instance - * of this class exists for each remote object. Automatically created - * by {@link RmiServiceExporter} for non-RMI service implementations. - * - *

This is an SPI class, not to be used directly by applications. - * - * @author Juergen Hoeller - * @since 14.05.2003 - * @see RmiServiceExporter - */ -class RmiInvocationWrapper implements RmiInvocationHandler { - - private final Object wrappedObject; - - private final RmiBasedExporter rmiExporter; - - - /** - * Create a new RmiInvocationWrapper for the given object - * @param wrappedObject the object to wrap with an RmiInvocationHandler - * @param rmiExporter the RMI exporter to handle the actual invocation - */ - public RmiInvocationWrapper(Object wrappedObject, RmiBasedExporter rmiExporter) { - Assert.notNull(wrappedObject, "Object to wrap is required"); - Assert.notNull(rmiExporter, "RMI exporter is required"); - this.wrappedObject = wrappedObject; - this.rmiExporter = rmiExporter; - } - - - /** - * Exposes the exporter's service interface, if any, as target interface. - * @see RmiBasedExporter#getServiceInterface() - */ - @Override - public String getTargetInterfaceName() { - Class ifc = this.rmiExporter.getServiceInterface(); - return (ifc != null ? ifc.getName() : null); - } - - /** - * Delegates the actual invocation handling to the RMI exporter. - * @see RmiBasedExporter#invoke(org.springframework.remoting.support.RemoteInvocation, Object) - */ - @Override - public Object invoke(RemoteInvocation invocation) - throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { - - return this.rmiExporter.invoke(invocation, this.wrappedObject); - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiProxyFactoryBean.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiProxyFactoryBean.java deleted file mode 100644 index 6866fa4e7..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiProxyFactoryBean.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import com.fr.third.springframework.aop.framework.ProxyFactory; -import com.fr.third.springframework.beans.factory.BeanClassLoaderAware; -import com.fr.third.springframework.beans.factory.FactoryBean; - -/** - * {@link FactoryBean} for RMI proxies, supporting both conventional RMI services - * and RMI invokers. Exposes the proxied service for use as a bean reference, - * using the specified service interface. Proxies will throw Spring's unchecked - * RemoteAccessException on remote invocation failure instead of RMI's RemoteException. - * - *

The service URL must be a valid RMI URL like "rmi://localhost:1099/myservice". - * RMI invokers work at the RmiInvocationHandler level, using the same invoker stub - * for any service. Service interfaces do not have to extend {@code java.rmi.Remote} - * or throw {@code java.rmi.RemoteException}. Of course, in and out parameters - * have to be serializable. - * - *

With conventional RMI services, this proxy factory is typically used with the - * RMI service interface. Alternatively, this factory can also proxy a remote RMI - * service with a matching non-RMI business interface, i.e. an interface that mirrors - * the RMI service methods but does not declare RemoteExceptions. In the latter case, - * RemoteExceptions thrown by the RMI stub will automatically get converted to - * Spring's unchecked RemoteAccessException. - * - *

The major advantage of RMI, compared to Hessian and Burlap, is serialization. - * Effectively, any serializable Java object can be transported without hassle. - * Hessian and Burlap have their own (de-)serialization mechanisms, but are - * HTTP-based and thus much easier to setup than RMI. Alternatively, consider - * Spring's HTTP invoker to combine Java serialization with HTTP-based transport. - * - * @author Juergen Hoeller - * @since 13.05.2003 - * @see #setServiceInterface - * @see #setServiceUrl - * @see RmiClientInterceptor - * @see RmiServiceExporter - * @see java.rmi.Remote - * @see java.rmi.RemoteException - * @see com.fr.third.springframework.remoting.RemoteAccessException - * @see com.fr.third.springframework.remoting.caucho.HessianProxyFactoryBean - * @see com.fr.third.springframework.remoting.caucho.BurlapProxyFactoryBean - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean - */ -public class RmiProxyFactoryBean extends RmiClientInterceptor implements FactoryBean, BeanClassLoaderAware { - - private Object serviceProxy; - - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - if (getServiceInterface() == null) { - throw new IllegalArgumentException("Property 'serviceInterface' is required"); - } - this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader()); - } - - - @Override - public Object getObject() { - return this.serviceProxy; - } - - @Override - public Class getObjectType() { - return getServiceInterface(); - } - - @Override - public boolean isSingleton() { - return true; - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiRegistryFactoryBean.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiRegistryFactoryBean.java deleted file mode 100644 index 1437d1b4e..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiRegistryFactoryBean.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMIClientSocketFactory; -import java.rmi.server.RMIServerSocketFactory; -import java.rmi.server.UnicastRemoteObject; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.fr.third.springframework.beans.factory.DisposableBean; -import com.fr.third.springframework.beans.factory.FactoryBean; -import com.fr.third.springframework.beans.factory.InitializingBean; - -/** - * {@link FactoryBean} that locates a {@link java.rmi.registry.Registry} and - * exposes it for bean references. Can also create a local RMI registry - * on the fly if none exists already. - * - *

Can be used to set up and pass around the actual Registry object to - * applications objects that need to work with RMI. One example for such an - * object that needs to work with RMI is Spring's {@link RmiServiceExporter}, - * which either works with a passed-in Registry reference or falls back to - * the registry as specified by its local properties and defaults. - * - *

Also useful to enforce creation of a local RMI registry at a given port, - * for example for a JMX connector. If used in conjunction with - * {@link com.fr.third.springframework.jmx.support.ConnectorServerFactoryBean}, - * it is recommended to mark the connector definition (ConnectorServerFactoryBean) - * as "depends-on" the registry definition (RmiRegistryFactoryBean), - * to guarantee starting up the registry first. - * - *

Note: The implementation of this class mirrors the corresponding logic - * in {@link RmiServiceExporter}, and also offers the same customization hooks. - * RmiServiceExporter implements its own registry lookup as a convenience: - * It is very common to simply rely on the registry defaults. - * - * @author Juergen Hoeller - * @since 1.2.3 - * @see RmiServiceExporter#setRegistry - * @see com.fr.third.springframework.jmx.support.ConnectorServerFactoryBean - * @see java.rmi.registry.Registry - * @see java.rmi.registry.LocateRegistry - */ -public class RmiRegistryFactoryBean implements FactoryBean, InitializingBean, DisposableBean { - - protected final Log logger = LogFactory.getLog(getClass()); - - private String host; - - private int port = Registry.REGISTRY_PORT; - - private RMIClientSocketFactory clientSocketFactory; - - private RMIServerSocketFactory serverSocketFactory; - - private Registry registry; - - private boolean alwaysCreate = false; - - private boolean created = false; - - - /** - * Set the host of the registry for the exported RMI service, - * i.e. {@code rmi://HOST:port/name} - *

Default is localhost. - */ - public void setHost(String host) { - this.host = host; - } - - /** - * Return the host of the registry for the exported RMI service. - */ - public String getHost() { - return this.host; - } - - /** - * Set the port of the registry for the exported RMI service, - * i.e. {@code rmi://host:PORT/name} - *

Default is {@code Registry.REGISTRY_PORT} (1099). - */ - public void setPort(int port) { - this.port = port; - } - - /** - * Return the port of the registry for the exported RMI service. - */ - public int getPort() { - return this.port; - } - - /** - * Set a custom RMI client socket factory to use for the RMI registry. - *

If the given object also implements {@code java.rmi.server.RMIServerSocketFactory}, - * it will automatically be registered as server socket factory too. - * @see #setServerSocketFactory - * @see java.rmi.server.RMIClientSocketFactory - * @see java.rmi.server.RMIServerSocketFactory - * @see java.rmi.registry.LocateRegistry#getRegistry(String, int, java.rmi.server.RMIClientSocketFactory) - */ - public void setClientSocketFactory(RMIClientSocketFactory clientSocketFactory) { - this.clientSocketFactory = clientSocketFactory; - } - - /** - * Set a custom RMI server socket factory to use for the RMI registry. - *

Only needs to be specified when the client socket factory does not - * implement {@code java.rmi.server.RMIServerSocketFactory} already. - * @see #setClientSocketFactory - * @see java.rmi.server.RMIClientSocketFactory - * @see java.rmi.server.RMIServerSocketFactory - * @see java.rmi.registry.LocateRegistry#createRegistry(int, RMIClientSocketFactory, java.rmi.server.RMIServerSocketFactory) - */ - public void setServerSocketFactory(RMIServerSocketFactory serverSocketFactory) { - this.serverSocketFactory = serverSocketFactory; - } - - /** - * Set whether to always create the registry in-process, - * not attempting to locate an existing registry at the specified port. - *

Default is "false". Switch this flag to "true" in order to avoid - * the overhead of locating an existing registry when you always - * intend to create a new registry in any case. - */ - public void setAlwaysCreate(boolean alwaysCreate) { - this.alwaysCreate = alwaysCreate; - } - - - @Override - public void afterPropertiesSet() throws Exception { - // Check socket factories for registry. - if (this.clientSocketFactory instanceof RMIServerSocketFactory) { - this.serverSocketFactory = (RMIServerSocketFactory) this.clientSocketFactory; - } - if ((this.clientSocketFactory != null && this.serverSocketFactory == null) || - (this.clientSocketFactory == null && this.serverSocketFactory != null)) { - throw new IllegalArgumentException( - "Both RMIClientSocketFactory and RMIServerSocketFactory or none required"); - } - - // Fetch RMI registry to expose. - this.registry = getRegistry(this.host, this.port, this.clientSocketFactory, this.serverSocketFactory); - } - - - /** - * Locate or create the RMI registry. - * @param registryHost the registry host to use (if this is specified, - * no implicit creation of a RMI registry will happen) - * @param registryPort the registry port to use - * @param clientSocketFactory the RMI client socket factory for the registry (if any) - * @param serverSocketFactory the RMI server socket factory for the registry (if any) - * @return the RMI registry - * @throws java.rmi.RemoteException if the registry couldn't be located or created - */ - protected Registry getRegistry(String registryHost, int registryPort, - RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory) - throws RemoteException { - - if (registryHost != null) { - // Host explicitly specified: only lookup possible. - if (logger.isInfoEnabled()) { - logger.info("Looking for RMI registry at port '" + registryPort + "' of host [" + registryHost + "]"); - } - Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory); - testRegistry(reg); - return reg; - } - - else { - return getRegistry(registryPort, clientSocketFactory, serverSocketFactory); - } - } - - /** - * Locate or create the RMI registry. - * @param registryPort the registry port to use - * @param clientSocketFactory the RMI client socket factory for the registry (if any) - * @param serverSocketFactory the RMI server socket factory for the registry (if any) - * @return the RMI registry - * @throws RemoteException if the registry couldn't be located or created - */ - protected Registry getRegistry( - int registryPort, RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory) - throws RemoteException { - - if (clientSocketFactory != null) { - if (this.alwaysCreate) { - logger.info("Creating new RMI registry"); - this.created = true; - return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory); - } - if (logger.isInfoEnabled()) { - logger.info("Looking for RMI registry at port '" + registryPort + "', using custom socket factory"); - } - synchronized (LocateRegistry.class) { - try { - // Retrieve existing registry. - Registry reg = LocateRegistry.getRegistry(null, registryPort, clientSocketFactory); - testRegistry(reg); - return reg; - } - catch (RemoteException ex) { - logger.debug("RMI registry access threw exception", ex); - logger.info("Could not detect RMI registry - creating new one"); - // Assume no registry found -> create new one. - this.created = true; - return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory); - } - } - } - - else { - return getRegistry(registryPort); - } - } - - /** - * Locate or create the RMI registry. - * @param registryPort the registry port to use - * @return the RMI registry - * @throws RemoteException if the registry couldn't be located or created - */ - protected Registry getRegistry(int registryPort) throws RemoteException { - if (this.alwaysCreate) { - logger.info("Creating new RMI registry"); - this.created = true; - return LocateRegistry.createRegistry(registryPort); - } - if (logger.isInfoEnabled()) { - logger.info("Looking for RMI registry at port '" + registryPort + "'"); - } - synchronized (LocateRegistry.class) { - try { - // Retrieve existing registry. - Registry reg = LocateRegistry.getRegistry(registryPort); - testRegistry(reg); - return reg; - } - catch (RemoteException ex) { - logger.debug("RMI registry access threw exception", ex); - logger.info("Could not detect RMI registry - creating new one"); - // Assume no registry found -> create new one. - this.created = true; - return LocateRegistry.createRegistry(registryPort); - } - } - } - - /** - * Test the given RMI registry, calling some operation on it to - * check whether it is still active. - *

Default implementation calls {@code Registry.list()}. - * @param registry the RMI registry to test - * @throws RemoteException if thrown by registry methods - * @see java.rmi.registry.Registry#list() - */ - protected void testRegistry(Registry registry) throws RemoteException { - registry.list(); - } - - - @Override - public Registry getObject() throws Exception { - return this.registry; - } - - @Override - public Class getObjectType() { - return (this.registry != null ? this.registry.getClass() : Registry.class); - } - - @Override - public boolean isSingleton() { - return true; - } - - - /** - * Unexport the RMI registry on bean factory shutdown, - * provided that this bean actually created a registry. - */ - @Override - public void destroy() throws RemoteException { - if (this.created) { - logger.info("Unexporting RMI registry"); - UnicastRemoteObject.unexportObject(this.registry, true); - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiServiceExporter.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiServiceExporter.java deleted file mode 100644 index a4d2fe3c8..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/RmiServiceExporter.java +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.fr.third.springframework.remoting.rmi; - -import java.rmi.AlreadyBoundException; -import java.rmi.NoSuchObjectException; -import java.rmi.NotBoundException; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMIClientSocketFactory; -import java.rmi.server.RMIServerSocketFactory; -import java.rmi.server.UnicastRemoteObject; - -import com.fr.third.springframework.beans.factory.DisposableBean; -import com.fr.third.springframework.beans.factory.InitializingBean; - -/** - * RMI exporter that exposes the specified service as RMI object with the specified name. - * Such services can be accessed via plain RMI or via {@link RmiProxyFactoryBean}. - * Also supports exposing any non-RMI service via RMI invokers, to be accessed via - * {@link RmiClientInterceptor} / {@link RmiProxyFactoryBean}'s automatic detection - * of such invokers. - * - *

With an RMI invoker, RMI communication works on the {@link RmiInvocationHandler} - * level, needing only one stub for any service. Service interfaces do not have to - * extend {@code java.rmi.Remote} or throw {@code java.rmi.RemoteException} - * on all methods, but in and out parameters have to be serializable. - * - *

The major advantage of RMI, compared to Hessian and Burlap, is serialization. - * Effectively, any serializable Java object can be transported without hassle. - * Hessian and Burlap have their own (de-)serialization mechanisms, but are - * HTTP-based and thus much easier to setup than RMI. Alternatively, consider - * Spring's HTTP invoker to combine Java serialization with HTTP-based transport. - * - *

Note: RMI makes a best-effort attempt to obtain the fully qualified host name. - * If one cannot be determined, it will fall back and use the IP address. Depending - * on your network configuration, in some cases it will resolve the IP to the loopback - * address. To ensure that RMI will use the host name bound to the correct network - * interface, you should pass the {@code java.rmi.server.hostname} property to the - * JVM that will export the registry and/or the service using the "-D" JVM argument. - * For example: {@code -Djava.rmi.server.hostname=myserver.com} - * - * @author Juergen Hoeller - * @since 13.05.2003 - * @see RmiClientInterceptor - * @see RmiProxyFactoryBean - * @see java.rmi.Remote - * @see java.rmi.RemoteException - * @see com.fr.third.springframework.remoting.caucho.HessianServiceExporter - * @see com.fr.third.springframework.remoting.caucho.BurlapServiceExporter - * @see com.fr.third.springframework.remoting.httpinvoker.HttpInvokerServiceExporter - */ -public class RmiServiceExporter extends RmiBasedExporter implements InitializingBean, DisposableBean { - - private String serviceName; - - private int servicePort = 0; // anonymous port - - private RMIClientSocketFactory clientSocketFactory; - - private RMIServerSocketFactory serverSocketFactory; - - private Registry registry; - - private String registryHost; - - private int registryPort = Registry.REGISTRY_PORT; - - private RMIClientSocketFactory registryClientSocketFactory; - - private RMIServerSocketFactory registryServerSocketFactory; - - private boolean alwaysCreateRegistry = false; - - private boolean replaceExistingBinding = true; - - private Remote exportedObject; - - private boolean createdRegistry = false; - - - /** - * Set the name of the exported RMI service, - * i.e. {@code rmi://host:port/NAME} - */ - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - /** - * Set the port that the exported RMI service will use. - *

Default is 0 (anonymous port). - */ - public void setServicePort(int servicePort) { - this.servicePort = servicePort; - } - - /** - * Set a custom RMI client socket factory to use for exporting the service. - *

If the given object also implements {@code java.rmi.server.RMIServerSocketFactory}, - * it will automatically be registered as server socket factory too. - * @see #setServerSocketFactory - * @see java.rmi.server.RMIClientSocketFactory - * @see java.rmi.server.RMIServerSocketFactory - * @see UnicastRemoteObject#exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory) - */ - public void setClientSocketFactory(RMIClientSocketFactory clientSocketFactory) { - this.clientSocketFactory = clientSocketFactory; - } - - /** - * Set a custom RMI server socket factory to use for exporting the service. - *

Only needs to be specified when the client socket factory does not - * implement {@code java.rmi.server.RMIServerSocketFactory} already. - * @see #setClientSocketFactory - * @see java.rmi.server.RMIClientSocketFactory - * @see java.rmi.server.RMIServerSocketFactory - * @see UnicastRemoteObject#exportObject(Remote, int, RMIClientSocketFactory, RMIServerSocketFactory) - */ - public void setServerSocketFactory(RMIServerSocketFactory serverSocketFactory) { - this.serverSocketFactory = serverSocketFactory; - } - - /** - * Specify the RMI registry to register the exported service with. - * Typically used in combination with RmiRegistryFactoryBean. - *

Alternatively, you can specify all registry properties locally. - * This exporter will then try to locate the specified registry, - * automatically creating a new local one if appropriate. - *

Default is a local registry at the default port (1099), - * created on the fly if necessary. - * @see RmiRegistryFactoryBean - * @see #setRegistryHost - * @see #setRegistryPort - * @see #setRegistryClientSocketFactory - * @see #setRegistryServerSocketFactory - */ - public void setRegistry(Registry registry) { - this.registry = registry; - } - - /** - * Set the host of the registry for the exported RMI service, - * i.e. {@code rmi://HOST:port/name} - *

Default is localhost. - */ - public void setRegistryHost(String registryHost) { - this.registryHost = registryHost; - } - - /** - * Set the port of the registry for the exported RMI service, - * i.e. {@code rmi://host:PORT/name} - *

Default is {@code Registry.REGISTRY_PORT} (1099). - * @see java.rmi.registry.Registry#REGISTRY_PORT - */ - public void setRegistryPort(int registryPort) { - this.registryPort = registryPort; - } - - /** - * Set a custom RMI client socket factory to use for the RMI registry. - *

If the given object also implements {@code java.rmi.server.RMIServerSocketFactory}, - * it will automatically be registered as server socket factory too. - * @see #setRegistryServerSocketFactory - * @see java.rmi.server.RMIClientSocketFactory - * @see java.rmi.server.RMIServerSocketFactory - * @see LocateRegistry#getRegistry(String, int, RMIClientSocketFactory) - */ - public void setRegistryClientSocketFactory(RMIClientSocketFactory registryClientSocketFactory) { - this.registryClientSocketFactory = registryClientSocketFactory; - } - - /** - * Set a custom RMI server socket factory to use for the RMI registry. - *

Only needs to be specified when the client socket factory does not - * implement {@code java.rmi.server.RMIServerSocketFactory} already. - * @see #setRegistryClientSocketFactory - * @see java.rmi.server.RMIClientSocketFactory - * @see java.rmi.server.RMIServerSocketFactory - * @see LocateRegistry#createRegistry(int, RMIClientSocketFactory, RMIServerSocketFactory) - */ - public void setRegistryServerSocketFactory(RMIServerSocketFactory registryServerSocketFactory) { - this.registryServerSocketFactory = registryServerSocketFactory; - } - - /** - * Set whether to always create the registry in-process, - * not attempting to locate an existing registry at the specified port. - *

Default is "false". Switch this flag to "true" in order to avoid - * the overhead of locating an existing registry when you always - * intend to create a new registry in any case. - */ - public void setAlwaysCreateRegistry(boolean alwaysCreateRegistry) { - this.alwaysCreateRegistry = alwaysCreateRegistry; - } - - /** - * Set whether to replace an existing binding in the RMI registry, - * that is, whether to simply override an existing binding with the - * specified service in case of a naming conflict in the registry. - *

Default is "true", assuming that an existing binding for this - * exporter's service name is an accidental leftover from a previous - * execution. Switch this to "false" to make the exporter fail in such - * a scenario, indicating that there was already an RMI object bound. - */ - public void setReplaceExistingBinding(boolean replaceExistingBinding) { - this.replaceExistingBinding = replaceExistingBinding; - } - - - @Override - public void afterPropertiesSet() throws RemoteException { - prepare(); - } - - /** - * Initialize this service exporter, registering the service as RMI object. - *

Creates an RMI registry on the specified port if none exists. - * @throws RemoteException if service registration failed - */ - public void prepare() throws RemoteException { - checkService(); - - if (this.serviceName == null) { - throw new IllegalArgumentException("Property 'serviceName' is required"); - } - - // Check socket factories for exported object. - if (this.clientSocketFactory instanceof RMIServerSocketFactory) { - this.serverSocketFactory = (RMIServerSocketFactory) this.clientSocketFactory; - } - if ((this.clientSocketFactory != null && this.serverSocketFactory == null) || - (this.clientSocketFactory == null && this.serverSocketFactory != null)) { - throw new IllegalArgumentException( - "Both RMIClientSocketFactory and RMIServerSocketFactory or none required"); - } - - // Check socket factories for RMI registry. - if (this.registryClientSocketFactory instanceof RMIServerSocketFactory) { - this.registryServerSocketFactory = (RMIServerSocketFactory) this.registryClientSocketFactory; - } - if (this.registryClientSocketFactory == null && this.registryServerSocketFactory != null) { - throw new IllegalArgumentException( - "RMIServerSocketFactory without RMIClientSocketFactory for registry not supported"); - } - - this.createdRegistry = false; - - // Determine RMI registry to use. - if (this.registry == null) { - this.registry = getRegistry(this.registryHost, this.registryPort, - this.registryClientSocketFactory, this.registryServerSocketFactory); - this.createdRegistry = true; - } - - // Initialize and cache exported object. - this.exportedObject = getObjectToExport(); - - if (logger.isInfoEnabled()) { - logger.info("Binding service '" + this.serviceName + "' to RMI registry: " + this.registry); - } - - // Export RMI object. - if (this.clientSocketFactory != null) { - UnicastRemoteObject.exportObject( - this.exportedObject, this.servicePort, this.clientSocketFactory, this.serverSocketFactory); - } - else { - UnicastRemoteObject.exportObject(this.exportedObject, this.servicePort); - } - - // Bind RMI object to registry. - try { - if (this.replaceExistingBinding) { - this.registry.rebind(this.serviceName, this.exportedObject); - } - else { - this.registry.bind(this.serviceName, this.exportedObject); - } - } - catch (AlreadyBoundException ex) { - // Already an RMI object bound for the specified service name... - unexportObjectSilently(); - throw new IllegalStateException( - "Already an RMI object bound for name '" + this.serviceName + "': " + ex.toString()); - } - catch (RemoteException ex) { - // Registry binding failed: let's unexport the RMI object as well. - unexportObjectSilently(); - throw ex; - } - } - - - /** - * Locate or create the RMI registry for this exporter. - * @param registryHost the registry host to use (if this is specified, - * no implicit creation of a RMI registry will happen) - * @param registryPort the registry port to use - * @param clientSocketFactory the RMI client socket factory for the registry (if any) - * @param serverSocketFactory the RMI server socket factory for the registry (if any) - * @return the RMI registry - * @throws RemoteException if the registry couldn't be located or created - */ - protected Registry getRegistry(String registryHost, int registryPort, - RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory) - throws RemoteException { - - if (registryHost != null) { - // Host explicitly specified: only lookup possible. - if (logger.isInfoEnabled()) { - logger.info("Looking for RMI registry at port '" + registryPort + "' of host [" + registryHost + "]"); - } - Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory); - testRegistry(reg); - return reg; - } - - else { - return getRegistry(registryPort, clientSocketFactory, serverSocketFactory); - } - } - - /** - * Locate or create the RMI registry for this exporter. - * @param registryPort the registry port to use - * @param clientSocketFactory the RMI client socket factory for the registry (if any) - * @param serverSocketFactory the RMI server socket factory for the registry (if any) - * @return the RMI registry - * @throws RemoteException if the registry couldn't be located or created - */ - protected Registry getRegistry( - int registryPort, RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory) - throws RemoteException { - - if (clientSocketFactory != null) { - if (this.alwaysCreateRegistry) { - logger.info("Creating new RMI registry"); - return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory); - } - if (logger.isInfoEnabled()) { - logger.info("Looking for RMI registry at port '" + registryPort + "', using custom socket factory"); - } - synchronized (LocateRegistry.class) { - try { - // Retrieve existing registry. - Registry reg = LocateRegistry.getRegistry(null, registryPort, clientSocketFactory); - testRegistry(reg); - return reg; - } - catch (RemoteException ex) { - logger.debug("RMI registry access threw exception", ex); - logger.info("Could not detect RMI registry - creating new one"); - // Assume no registry found -> create new one. - return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory); - } - } - } - - else { - return getRegistry(registryPort); - } - } - - /** - * Locate or create the RMI registry for this exporter. - * @param registryPort the registry port to use - * @return the RMI registry - * @throws RemoteException if the registry couldn't be located or created - */ - protected Registry getRegistry(int registryPort) throws RemoteException { - if (this.alwaysCreateRegistry) { - logger.info("Creating new RMI registry"); - return LocateRegistry.createRegistry(registryPort); - } - if (logger.isInfoEnabled()) { - logger.info("Looking for RMI registry at port '" + registryPort + "'"); - } - synchronized (LocateRegistry.class) { - try { - // Retrieve existing registry. - Registry reg = LocateRegistry.getRegistry(registryPort); - testRegistry(reg); - return reg; - } - catch (RemoteException ex) { - logger.debug("RMI registry access threw exception", ex); - logger.info("Could not detect RMI registry - creating new one"); - // Assume no registry found -> create new one. - return LocateRegistry.createRegistry(registryPort); - } - } - } - - /** - * Test the given RMI registry, calling some operation on it to - * check whether it is still active. - *

Default implementation calls {@code Registry.list()}. - * @param registry the RMI registry to test - * @throws RemoteException if thrown by registry methods - * @see java.rmi.registry.Registry#list() - */ - protected void testRegistry(Registry registry) throws RemoteException { - registry.list(); - } - - - /** - * Unbind the RMI service from the registry on bean factory shutdown. - */ - @Override - public void destroy() throws RemoteException { - if (logger.isInfoEnabled()) { - logger.info("Unbinding RMI service '" + this.serviceName + - "' from registry" + (this.createdRegistry ? (" at port '" + this.registryPort + "'") : "")); - } - try { - this.registry.unbind(this.serviceName); - } - catch (NotBoundException ex) { - if (logger.isWarnEnabled()) { - logger.warn("RMI service '" + this.serviceName + "' is not bound to registry" + - (this.createdRegistry ? (" at port '" + this.registryPort + "' anymore") : ""), ex); - } - } - finally { - unexportObjectSilently(); - } - } - - /** - * Unexport the registered RMI object, logging any exception that arises. - */ - private void unexportObjectSilently() { - try { - UnicastRemoteObject.unexportObject(this.exportedObject, true); - } - catch (NoSuchObjectException ex) { - if (logger.isWarnEnabled()) { - logger.warn("RMI object for service '" + this.serviceName + "' is not exported anymore", ex); - } - } - } - -} diff --git a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/package-info.java b/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/package-info.java deleted file mode 100644 index 51f329781..000000000 --- a/fine-spring/src/main/java/com/fr/third/springframework/remoting/rmi/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Remoting classes for conventional RMI and transparent remoting via - * RMI invokers. Provides a proxy factory for accessing RMI services, - * and an exporter for making beans available to RMI clients. - */ -package com.fr.third.springframework.remoting.rmi; From 7704cea865650af45b1e99522562e7c2eb7bc2f3 Mon Sep 17 00:00:00 2001 From: "Yuan.Wang" <1536296691@qq.com> Date: Tue, 23 May 2023 17:37:33 +0800 Subject: [PATCH 2/5] =?UTF-8?q?REPORT-95576=20spring=20framework=20?= =?UTF-8?q?=E9=AB=98=E5=8D=B1=E6=BC=8F=E6=B4=9E=EF=BC=8C=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fine-spring/readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fine-spring/readme.md b/fine-spring/readme.md index dfb6c1024..4e69f76db 100644 --- a/fine-spring/readme.md +++ b/fine-spring/readme.md @@ -1,4 +1,5 @@ 1 spring版本4.3.29.RELEASE
2 fine-spring内容见https://kms.fineres.com/pages/viewpage.action?pageId=152798513
3 定制内容处均有"// 定制"注释
-4 去除对jackson的ObjectMapper的支持:DEC-17331
\ No newline at end of file +4 去除对jackson的ObjectMapper的支持:DEC-17331
+5、删除com.fr.third.springframework.remoting.caucho ;com.fr.third.springframework.remoting.httpinvoker; com.fr.third.springframework.remoting.rmi.*
\ No newline at end of file From 246b3602b5aadb7592cff0fd75130bf45ccc95b5 Mon Sep 17 00:00:00 2001 From: "Yuan.Wang" <1536296691@qq.com> Date: Wed, 24 May 2023 14:39:39 +0800 Subject: [PATCH 3/5] =?UTF-8?q?REPORT-95576=20spring=20framework=20?= =?UTF-8?q?=E9=AB=98=E5=8D=B1=E6=BC=8F=E6=B4=9E=EF=BC=8C=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbstractRemoteSlsbInvokerInterceptor.java | 4 +- .../SimpleRemoteSlsbInvokerInterceptor.java | 40 +++---------------- 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java b/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java index 21cf6add0..84dec0b06 100644 --- a/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java +++ b/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java @@ -22,13 +22,11 @@ import java.rmi.RemoteException; import javax.ejb.EJBHome; import javax.ejb.EJBObject; import javax.naming.NamingException; -import javax.rmi.PortableRemoteObject; import org.aopalliance.intercept.MethodInvocation; import com.fr.third.springframework.remoting.RemoteConnectFailureException; import com.fr.third.springframework.remoting.RemoteLookupFailureException; -import com.fr.third.springframework.remoting.rmi.RmiClientInterceptorUtils; /** * Base class for interceptors proxying remote Stateless Session Beans. @@ -162,7 +160,7 @@ public abstract class AbstractRemoteSlsbInvokerInterceptor extends AbstractSlsbI * @see com.fr.third.springframework.remoting.rmi.RmiClientInterceptorUtils#isConnectFailure */ protected boolean isConnectFailure(RemoteException ex) { - return RmiClientInterceptorUtils.isConnectFailure(ex); + throw new UnsupportedOperationException(); } private Object handleRemoteConnectFailure(MethodInvocation invocation, Exception ex) throws Throwable { diff --git a/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java b/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java index 58c97eb76..2360b6808 100644 --- a/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java +++ b/fine-spring/src/main/java/com/fr/third/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java @@ -16,17 +16,12 @@ package com.fr.third.springframework.ejb.access; -import java.lang.reflect.InvocationTargetException; -import java.rmi.RemoteException; -import javax.ejb.CreateException; -import javax.ejb.EJBObject; -import javax.naming.NamingException; - +import com.fr.third.springframework.beans.factory.DisposableBean; import org.aopalliance.intercept.MethodInvocation; -import com.fr.third.springframework.beans.factory.DisposableBean; -import com.fr.third.springframework.remoting.RemoteLookupFailureException; -import com.fr.third.springframework.remoting.rmi.RmiClientInterceptorUtils; +import javax.ejb.EJBObject; +import javax.naming.NamingException; +import java.lang.reflect.InvocationTargetException; /** * Basic invoker for a remote Stateless Session Bean. @@ -92,32 +87,7 @@ public class SimpleRemoteSlsbInvokerInterceptor extends AbstractRemoteSlsbInvoke */ @Override protected Object doInvoke(MethodInvocation invocation) throws Throwable { - Object ejb = null; - try { - ejb = getSessionBeanInstance(); - return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, ejb); - } - catch (NamingException ex) { - throw new RemoteLookupFailureException("Failed to locate remote EJB [" + getJndiName() + "]", ex); - } - catch (InvocationTargetException ex) { - Throwable targetEx = ex.getTargetException(); - if (targetEx instanceof RemoteException) { - RemoteException rex = (RemoteException) targetEx; - throw RmiClientInterceptorUtils.convertRmiAccessException( - invocation.getMethod(), rex, isConnectFailure(rex), getJndiName()); - } - else if (targetEx instanceof CreateException) { - throw RmiClientInterceptorUtils.convertRmiAccessException( - invocation.getMethod(), targetEx, "Could not create remote EJB [" + getJndiName() + "]"); - } - throw targetEx; - } - finally { - if (ejb instanceof EJBObject) { - releaseSessionBeanInstance((EJBObject) ejb); - } - } + throw new UnsupportedOperationException(); } /** From 373f91a09a51fffb382341223228774ab5803cac Mon Sep 17 00:00:00 2001 From: "Yuan.Wang" <1536296691@qq.com> Date: Mon, 5 Jun 2023 16:54:29 +0800 Subject: [PATCH 4/5] =?UTF-8?q?REPORT-95578=20dom4j=E5=8D=87=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fine-org-dom4j/README.md | 2 +- .../src/main/java/org/dom4j/Attribute.java | 194 +- .../src/main/java/org/dom4j/Branch.java | 493 ++- .../src/main/java/org/dom4j/CDATA.java | 7 +- .../main/java/org/dom4j/CharacterData.java | 7 +- .../src/main/java/org/dom4j/Comment.java | 7 +- .../src/main/java/org/dom4j/Document.java | 17 +- .../java/org/dom4j/DocumentException.java | 64 +- .../main/java/org/dom4j/DocumentFactory.java | 48 +- .../main/java/org/dom4j/DocumentHelper.java | 81 +- .../src/main/java/org/dom4j/DocumentType.java | 17 +- .../src/main/java/org/dom4j/Element.java | 1493 ++++----- .../main/java/org/dom4j/ElementHandler.java | 7 +- .../src/main/java/org/dom4j/ElementPath.java | 3 +- .../src/main/java/org/dom4j/Entity.java | 7 +- .../java/org/dom4j/IllegalAddException.java | 6 +- .../java/org/dom4j/InvalidXPathException.java | 16 +- .../src/main/java/org/dom4j/Namespace.java | 10 +- .../src/main/java/org/dom4j/Node.java | 21 +- .../src/main/java/org/dom4j/NodeFilter.java | 7 +- .../java/org/dom4j/ProcessingInstruction.java | 11 +- .../src/main/java/org/dom4j/QName.java | 127 +- .../src/main/java/org/dom4j/Text.java | 7 +- .../src/main/java/org/dom4j/Visitor.java | 11 +- .../main/java/org/dom4j/VisitorSupport.java | 6 +- .../src/main/java/org/dom4j/XPath.java | 473 ++- .../main/java/org/dom4j/XPathException.java | 6 +- .../java/org/dom4j/bean/BeanAttribute.java | 2 +- .../org/dom4j/bean/BeanAttributeList.java | 30 +- .../org/dom4j/bean/BeanDocumentFactory.java | 4 +- .../main/java/org/dom4j/bean/BeanElement.java | 14 +- .../java/org/dom4j/bean/BeanMetaData.java | 31 +- .../java/org/dom4j/bean/package-info.java | 4 + .../src/main/java/org/dom4j/bean/package.html | 10 - .../org/dom4j/datatype/DatatypeAttribute.java | 2 +- .../datatype/DatatypeDocumentFactory.java | 2 +- .../org/dom4j/datatype/DatatypeElement.java | 2 +- .../datatype/DatatypeElementFactory.java | 10 +- .../datatype/InvalidSchemaException.java | 2 +- .../org/dom4j/datatype/NamedTypeResolver.java | 15 +- .../java/org/dom4j/datatype/SchemaParser.java | 75 +- .../java/org/dom4j/datatype/package-info.java | 4 + .../main/java/org/dom4j/datatype/package.html | 10 - .../main/java/org/dom4j/dom/DOMAttribute.java | 10 +- .../org/dom4j/dom/DOMAttributeNodeMap.java | 2 +- .../src/main/java/org/dom4j/dom/DOMCDATA.java | 10 +- .../main/java/org/dom4j/dom/DOMComment.java | 9 +- .../main/java/org/dom4j/dom/DOMDocument.java | 18 +- .../org/dom4j/dom/DOMDocumentFactory.java | 36 +- .../java/org/dom4j/dom/DOMDocumentType.java | 9 +- .../main/java/org/dom4j/dom/DOMElement.java | 15 +- .../org/dom4j/dom/DOMEntityReference.java | 9 +- .../main/java/org/dom4j/dom/DOMNamespace.java | 9 +- .../java/org/dom4j/dom/DOMNodeHelper.java | 35 +- .../dom4j/dom/DOMProcessingInstruction.java | 11 +- .../src/main/java/org/dom4j/dom/DOMText.java | 9 +- .../main/java/org/dom4j/dom/package-info.java | 4 + .../src/main/java/org/dom4j/dom/package.html | 10 - .../java/org/dom4j/dtd/AttributeDecl.java | 4 +- .../src/main/java/org/dom4j/dtd/Decl.java | 7 + .../main/java/org/dom4j/dtd/ElementDecl.java | 4 +- .../org/dom4j/dtd/ExternalEntityDecl.java | 4 +- .../org/dom4j/dtd/InternalEntityDecl.java | 4 +- .../main/java/org/dom4j/dtd/package-info.java | 4 + .../src/main/java/org/dom4j/dtd/package.html | 9 - .../java/org/dom4j/io/DOMDocumentResult.java | 102 + .../src/main/java/org/dom4j/io/DOMReader.java | 13 +- .../org/dom4j/io/DOMSAXContentHandler.java | 548 ++++ .../src/main/java/org/dom4j/io/DOMWriter.java | 74 +- .../java/org/dom4j/io/DispatchHandler.java | 24 +- .../org/dom4j/io/DocumentInputSource.java | 2 +- .../java/org/dom4j/io/DocumentResult.java | 2 +- .../java/org/dom4j/io/DocumentSource.java | 10 +- .../main/java/org/dom4j/io/ElementStack.java | 2 +- .../main/java/org/dom4j/io/HTMLWriter.java | 174 +- .../main/java/org/dom4j/io/JAXPHelper.java | 2 +- .../main/java/org/dom4j/io/OutputFormat.java | 58 +- .../org/dom4j/io/PruningElementStack.java | 2 +- .../java/org/dom4j/io/SAXContentHandler.java | 39 +- .../java/org/dom4j/io/SAXEventRecorder.java | 68 +- .../src/main/java/org/dom4j/io/SAXHelper.java | 54 +- .../main/java/org/dom4j/io/SAXModifier.java | 18 +- .../src/main/java/org/dom4j/io/SAXReader.java | 1853 ++++++----- .../main/java/org/dom4j/io/SAXValidator.java | 2 +- .../src/main/java/org/dom4j/io/SAXWriter.java | 70 +- .../java/org/dom4j/io/STAXEventReader.java | 20 +- .../java/org/dom4j/io/STAXEventWriter.java | 26 +- .../src/main/java/org/dom4j/io/XMLResult.java | 2 +- .../src/main/java/org/dom4j/io/XMLWriter.java | 339 +- .../main/java/org/dom4j/io/XPP3Reader.java | 2 +- .../src/main/java/org/dom4j/io/XPPReader.java | 2 +- .../main/java/org/dom4j/io/package-info.java | 4 + .../src/main/java/org/dom4j/io/package.html | 10 - .../java/org/dom4j/jaxb/JAXBModifier.java | 12 +- .../main/java/org/dom4j/jaxb/JAXBReader.java | 6 +- .../main/java/org/dom4j/jaxb/JAXBWriter.java | 8 +- .../src/main/java/org/dom4j/package-info.java | 4 + .../src/main/java/org/dom4j/package.html | 10 - .../src/main/java/org/dom4j/rule/Action.java | 2 +- .../src/main/java/org/dom4j/rule/Mode.java | 16 +- .../main/java/org/dom4j/rule/NullAction.java | 2 +- .../src/main/java/org/dom4j/rule/Pattern.java | 2 +- .../src/main/java/org/dom4j/rule/Rule.java | 547 ++-- .../main/java/org/dom4j/rule/RuleManager.java | 16 +- .../src/main/java/org/dom4j/rule/RuleSet.java | 4 +- .../main/java/org/dom4j/rule/Stylesheet.java | 210 +- .../java/org/dom4j/rule/package-info.java | 5 + .../src/main/java/org/dom4j/rule/package.html | 14 - .../dom4j/rule/pattern/DefaultPattern.java | 2 +- .../dom4j/rule/pattern/NodeTypePattern.java | 2 +- .../java/org/dom4j/swing/BranchTreeNode.java | 16 +- .../org/dom4j/swing/DocumentTreeModel.java | 2 +- .../java/org/dom4j/swing/LeafTreeNode.java | 6 +- .../dom4j/swing/XMLTableColumnDefinition.java | 4 +- .../org/dom4j/swing/XMLTableDefinition.java | 18 +- .../java/org/dom4j/swing/XMLTableModel.java | 9 +- .../java/org/dom4j/swing/package-info.java | 4 + .../main/java/org/dom4j/swing/package.html | 10 - .../org/dom4j/tree/AbstractAttribute.java | 16 +- .../java/org/dom4j/tree/AbstractBranch.java | 89 +- .../java/org/dom4j/tree/AbstractCDATA.java | 2 +- .../org/dom4j/tree/AbstractCharacterData.java | 2 +- .../java/org/dom4j/tree/AbstractComment.java | 2 +- .../java/org/dom4j/tree/AbstractDocument.java | 37 +- .../org/dom4j/tree/AbstractDocumentType.java | 26 +- .../java/org/dom4j/tree/AbstractElement.java | 2767 ++++++++--------- .../java/org/dom4j/tree/AbstractEntity.java | 2 +- .../java/org/dom4j/tree/AbstractNode.java | 19 +- .../tree/AbstractProcessingInstruction.java | 32 +- .../java/org/dom4j/tree/AbstractText.java | 2 +- .../main/java/org/dom4j/tree/BackedList.java | 97 +- .../main/java/org/dom4j/tree/BaseElement.java | 30 +- .../dom4j/tree/ConcurrentReaderHashMap.java | 1284 -------- .../org/dom4j/tree/ContentListFacade.java | 84 +- .../java/org/dom4j/tree/DefaultAttribute.java | 2 +- .../java/org/dom4j/tree/DefaultCDATA.java | 2 +- .../java/org/dom4j/tree/DefaultComment.java | 2 +- .../java/org/dom4j/tree/DefaultDocument.java | 85 +- .../org/dom4j/tree/DefaultDocumentType.java | 16 +- .../java/org/dom4j/tree/DefaultElement.java | 312 +- .../java/org/dom4j/tree/DefaultEntity.java | 2 +- .../java/org/dom4j/tree/DefaultNamespace.java | 2 +- .../tree/DefaultProcessingInstruction.java | 10 +- .../main/java/org/dom4j/tree/DefaultText.java | 2 +- .../java/org/dom4j/tree/ElementIterator.java | 9 +- .../org/dom4j/tree/ElementNameIterator.java | 9 +- .../org/dom4j/tree/ElementQNameIterator.java | 9 +- .../java/org/dom4j/tree/FilterIterator.java | 20 +- .../org/dom4j/tree/FlyweightAttribute.java | 2 +- .../java/org/dom4j/tree/FlyweightCDATA.java | 2 +- .../java/org/dom4j/tree/FlyweightComment.java | 2 +- .../java/org/dom4j/tree/FlyweightEntity.java | 4 +- .../tree/FlyweightProcessingInstruction.java | 14 +- .../java/org/dom4j/tree/FlyweightText.java | 2 +- .../java/org/dom4j/tree/NamespaceCache.java | 68 +- .../java/org/dom4j/tree/NamespaceStack.java | 42 +- .../main/java/org/dom4j/tree/QNameCache.java | 66 +- .../java/org/dom4j/tree/SingleIterator.java | 12 +- .../java/org/dom4j/tree/package-info.java | 4 + .../src/main/java/org/dom4j/tree/package.html | 12 - .../java/org/dom4j/util/AttributeHelper.java | 2 +- .../dom4j/util/IndexedDocumentFactory.java | 2 +- .../java/org/dom4j/util/IndexedElement.java | 99 +- .../java/org/dom4j/util/NodeComparator.java | 81 +- .../dom4j/util/NonLazyDocumentFactory.java | 2 +- .../java/org/dom4j/util/NonLazyElement.java | 2 +- .../org/dom4j/util/PerThreadSingleton.java | 22 +- .../org/dom4j/util/ProxyDocumentFactory.java | 4 +- .../java/org/dom4j/util/SimpleSingleton.java | 14 +- .../org/dom4j/util/SingletonStrategy.java | 14 +- .../main/java/org/dom4j/util/StringUtils.java | 44 + .../org/dom4j/util/UserDataAttribute.java | 2 +- .../dom4j/util/UserDataDocumentFactory.java | 2 +- .../java/org/dom4j/util/UserDataElement.java | 2 +- .../java/org/dom4j/util/XMLErrorHandler.java | 2 +- .../java/org/dom4j/util/package-info.java | 4 + .../src/main/java/org/dom4j/util/package.html | 9 - .../java/org/dom4j/xpath/DefaultXPath.java | 64 +- .../java/org/dom4j/xpath/XPathPattern.java | 11 +- .../main/java/org/dom4j/xpath/overview.html | 9 - .../java/org/dom4j/xpath/package-info.java | 6 + .../main/java/org/dom4j/xpath/package.html | 13 - .../java/org/dom4j/xpp/ProxyXmlStartTag.java | 103 +- .../main/java/org/dom4j/xpp/package-info.java | 4 + .../src/main/java/org/dom4j/xpp/package.html | 14 - 185 files changed, 6096 insertions(+), 7688 deletions(-) create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/bean/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/bean/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/datatype/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/datatype/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/dom/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/dom/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/dtd/Decl.java create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/dtd/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/dtd/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/io/DOMDocumentResult.java create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/io/DOMSAXContentHandler.java create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/io/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/io/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/rule/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/rule/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/swing/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/swing/package.html delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/tree/ConcurrentReaderHashMap.java create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/tree/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/tree/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/util/StringUtils.java create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/util/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/util/package.html delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/xpath/overview.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/xpath/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/xpath/package.html create mode 100644 fine-org-dom4j/src/main/java/org/dom4j/xpp/package-info.java delete mode 100644 fine-org-dom4j/src/main/java/org/dom4j/xpp/package.html diff --git a/fine-org-dom4j/README.md b/fine-org-dom4j/README.md index d9fe5133f..5d8795f24 100644 --- a/fine-org-dom4j/README.md +++ b/fine-org-dom4j/README.md @@ -1,2 +1,2 @@ dom4j的源码地址:https://github.com/dom4j/dom4j
-版本:1.6.1
\ No newline at end of file +版本:2.1.4
\ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Attribute.java b/fine-org-dom4j/src/main/java/org/dom4j/Attribute.java index 61ef0b413..752752700 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Attribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Attribute.java @@ -8,131 +8,103 @@ package org.dom4j; /** - *

* Attribute defines an XML attribute. An attribute may have a * name, an optional namespace and a value. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ +@SuppressWarnings("unused") public interface Attribute extends Node { - /** - *

- * Returns the QName of this attribute which represents the - * local name, the qualified name and the Namespace. - *

- * - * @return the QName associated with this attribute - */ - QName getQName(); + /** + * Returns the QName of this attribute which represents the + * local name, the qualified name and the Namespace. + * + * @return the QName associated with this attribute + */ + QName getQName(); - /** - *

- * Returns the Namespace of this element if one exists - * otherwise null is returned returned. - *

- * - * @return the Namespace associated with this node - */ - Namespace getNamespace(); + /** + * Returns the Namespace of this element if one exists + * otherwise null is returned returned. + * + * @return the Namespace associated with this node + */ + Namespace getNamespace(); - /** - *

- * Sets the Namespace of this element or if this element is - * read only then an UnsupportedOperationException is thrown. - *

- * - * @param namespace - * is the Namespace to associate with this element - */ - void setNamespace(Namespace namespace); + /** + * Sets the Namespace of this element or if this element is + * read only then an UnsupportedOperationException is thrown. + * + * @param namespace is the Namespace to associate with this element + */ + void setNamespace(Namespace namespace); - /** - *

- * Returns the namespace prefix of this element if one exists otherwise an - * empty String is returned. - *

- * - * @return the prefix of the Namespace of this element or an - * empty String - */ - String getNamespacePrefix(); + /** + * Returns the namespace prefix of this element if one exists otherwise an + * empty String is returned. + * + * @return the prefix of the Namespace of this element or an + * empty String + */ + String getNamespacePrefix(); - /** - *

- * Returns the URI mapped to the namespace of this element if one exists - * otherwise an empty String is returned. - *

- * - * @return the URI for the Namespace of this element or an - * empty String - */ - String getNamespaceURI(); + /** + * Returns the URI mapped to the namespace of this element if one exists + * otherwise an empty String is returned. + * + * @return the URI for the Namespace of this element or an + * empty String + */ + String getNamespaceURI(); - /** - *

- * Returns the fully qualified name of this element. - *

- * - *

- * This will be the same as the value returned from {@link Node#getName()} - * if this element has no namespace attached to this element or an - * expression of the form - * - *

-     * getNamespacePrefix() + ":" + getName()
-     * 
- * - * will be returned. - *

- * - * @return the fully qualified name of the element - */ - String getQualifiedName(); + /** + * Returns the fully qualified name of this element. + * + * This will be the same as the value returned from {@link Node#getName()} + * if this element has no namespace attached to this element or an + * expression of the form + *
+	 * getNamespacePrefix() + ":" + getName()
+	 * 
+ * will be returned. + * + * @return the fully qualified name of the element + */ + String getQualifiedName(); - /** - *

- * Returns the value of the attribute. This method returns the same value as - * the {@link Node#getText()}method. - *

- * - * @return the value of the attribute - */ - String getValue(); + /** + * Returns the value of the attribute. This method returns the same value as + * the {@link Node#getText()}method. + * + * @return the value of the attribute + */ + String getValue(); - /** - *

- * Sets the value of this attribute or this method will throw an - * UnsupportedOperationException if it is read-only. - *

- * - * @param value - * is the new value of this attribute - */ - void setValue(String value); + /** + * Sets the value of this attribute or this method will throw an + * UnsupportedOperationException if it is read-only. + * + * @param value is the new value of this attribute + */ + void setValue(String value); - /** - *

- * Accesses the data of this attribute which may implement data typing - * bindings such as XML Schema or Java Bean - * bindings or will return the same value as {@link Node#getText()}. - *

- * - * @return the attribute data - */ - Object getData(); + /** + * Accesses the data of this attribute which may implement data typing + * bindings such as XML Schema or Java Bean + * bindings or will return the same value as {@link Node#getText()}. + * + * @return the attribute data + */ + Object getData(); - /** - *

- * Sets the data value of this attribute if this element supports data - * binding or calls {@link Node#setText(String)}if it doesn't. - *

- * - * @param data - * the attribute data - */ - void setData(Object data); + /** + * Sets the data value of this attribute if this element supports data + * binding or calls {@link Node#setText(String)}if it doesn't. + * + * @param data the attribute data + */ + void setData(Object data); } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Branch.java b/fine-org-dom4j/src/main/java/org/dom4j/Branch.java index 4074a588d..c7d36c2f6 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Branch.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Branch.java @@ -11,306 +11,263 @@ import java.util.Iterator; import java.util.List; /** - *

* Branch interface defines the common behaviour for Nodes which * can contain child nodes (content) such as XML elements and documents. This * interface allows both elements and documents to be treated in a polymorphic * manner when changing or navigating child nodes (content). - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.32 $ */ +@SuppressWarnings("unused") public interface Branch extends Node { - /** - * Returns the Node at the specified index position. - * - * @param index - * the index of the node to return. - * - * @return the Node at the specified position. - * - * @throws IndexOutOfBoundsException - * if the index is out of range (index < 0 || index >= - * {@link Branch#nodeCount()}). - */ - Node node(int index) throws IndexOutOfBoundsException; + /** + * Returns the Node at the specified index position. + * + * @param index the index of the node to return. + * @return the Node at the specified position. + * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index >= + * {@link Branch#nodeCount()}). + */ + Node node(int index) throws IndexOutOfBoundsException; - /** - * Returns the index of the given node if it is a child node of this branch - * or -1 if the given node is not a child node. - * - * @param node - * the content child node to find. - * - * @return the index of the given node starting at 0 or -1 if the node is - * not a child node of this branch - */ - int indexOf(Node node); + /** + * Returns the index of the given node if it is a child node of this branch + * or -1 if the given node is not a child node. + * + * @param node the content child node to find. + * @return the index of the given node starting at 0 or -1 if the node is + * not a child node of this branch + */ + int indexOf(Node node); - /** - * Returns the number of Node instances that this branch - * contains. - * - * @return the number of nodes this branch contains - */ - int nodeCount(); + /** + * Returns the number of Node instances that this branch + * contains. + * + * @return the number of nodes this branch contains + */ + int nodeCount(); - /** - * Returns the element of the given ID attribute value. If this tree is - * capable of understanding which attribute value should be used for the ID - * then it should be used, otherwise this method should return null. - * - * @param elementID - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - Element elementByID(String elementID); + /** + * Returns the element of the given ID attribute value. If this tree is + * capable of understanding which attribute value should be used for the ID + * then it should be used, otherwise this method should return null. + * + * @param elementID DOCUMENT ME! + * @return DOCUMENT ME! + */ + Element elementByID(String elementID); - /** - *

- * Returns the content nodes of this branch as a backed {@link List}so that - * the content of this branch may be modified directly using the - * {@link List}interface. The List is backed by the - * Branch so that changes to the list are reflected in the - * branch and vice versa. - *

- * - * @return the nodes that this branch contains as a List - */ - List content(); + /** + * Returns the content nodes of this branch as a backed {@link List}so that + * the content of this branch may be modified directly using the + * {@link List}interface. The List is backed by the + * Branch so that changes to the list are reflected in the + * branch and vice versa. + * + * @return the nodes that this branch contains as a List + */ + List content(); - /** - * Returns an iterator through the content nodes of this branch - * - * @return an iterator through the content nodes of this branch - */ - Iterator nodeIterator(); + /** + * Returns an iterator through the content nodes of this branch + * + * @return an iterator through the content nodes of this branch + */ + Iterator nodeIterator(); - /** - * Sets the contents of this branch as a List of - * Node instances. - * - * @param content - * is the list of nodes to use as the content for this branch. - */ - void setContent(List content); + /** + * Sets the contents of this branch as a List of + * Node instances. + * + * @param content is the list of nodes to use as the content for this branch. + */ + void setContent(List content); - /** - * Appends the content of the given branch to this branch instance. This - * method behaves like the {@link - * java.util.Collection#addAll(java.util.Collection)} method. - * - * @param branch - * is the branch whose content will be added to me. - */ - void appendContent(Branch branch); + /** + * Appends the content of the given branch to this branch instance. This + * method behaves like the {@link + * java.util.Collection#addAll(java.util.Collection)} method. + * + * @param branch is the branch whose content will be added to me. + */ + void appendContent(Branch branch); - /** - * Clears the content for this branch, removing any Node - * instances this branch may contain. - */ - void clearContent(); + /** + * Clears the content for this branch, removing any Node + * instances this branch may contain. + */ + void clearContent(); - /** - *

- * Returns a list of all the processing instructions in this branch. The - * list is backed by this branch so that changes to the list will be - * reflected in the branch but the reverse is not the case. - *

- * - * @return a backed list of the processing instructions - */ - List processingInstructions(); + /** + * Returns a list of all the processing instructions in this branch. The + * list is backed by this branch so that changes to the list will be + * reflected in the branch but the reverse is not the case. + * + * @return a backed list of the processing instructions + */ + List processingInstructions(); - /** - *

- * Returns a list of the processing instructions for the given target. The - * list is backed by this branch so that changes to the list will be - * reflected in the branch but the reverse is not the case. - *

- * - * @param target - * DOCUMENT ME! - * - * @return a backed list of the processing instructions - */ - List processingInstructions(String target); + /** + * Returns a list of the processing instructions for the given target. The + * list is backed by this branch so that changes to the list will be + * reflected in the branch but the reverse is not the case. + * + * @param target DOCUMENT ME! + * @return a backed list of the processing instructions + */ + List processingInstructions(String target); - /** - * DOCUMENT ME! - * - * @param target - * DOCUMENT ME! - * - * @return the processing instruction for the given target - */ - ProcessingInstruction processingInstruction(String target); + /** + * DOCUMENT ME! + * + * @param target DOCUMENT ME! + * @return the processing instruction for the given target + */ + ProcessingInstruction processingInstruction(String target); - /** - * Sets all the processing instructions for this branch - * - * @param listOfPIs - * DOCUMENT ME! - */ - void setProcessingInstructions(List listOfPIs); + /** + * Sets all the processing instructions for this branch + * + * @param listOfPIs DOCUMENT ME! + */ + void setProcessingInstructions(List listOfPIs); - /** - * Adds a new Element node with the given name to this branch - * and returns a reference to the new node. - * - * @param name - * is the name for the Element node. - * - * @return the newly added Element node. - */ - Element addElement(String name); + /** + * Adds a new Element node with the given name to this branch + * and returns a reference to the new node. + * + * @param name is the name for the Element node. + * @return the newly added Element node. + */ + Element addElement(String name); - /** - * Adds a new Element node with the given {@link QName}to - * this branch and returns a reference to the new node. - * - * @param qname - * is the qualified name for the Element node. - * - * @return the newly added Element node. - */ - Element addElement(QName qname); + /** + * Adds a new Element node with the given {@link QName}to + * this branch and returns a reference to the new node. + * + * @param qname is the qualified name for the Element node. + * @return the newly added Element node. + */ + Element addElement(QName qname); - /** - * Adds a new Element node with the given qualified name and - * namespace URI to this branch and returns a reference to the new node. - * - * @param qualifiedName - * is the fully qualified name of the Element - * @param namespaceURI - * is the URI of the namespace to use - * - * @return the newly added Element node. - */ - Element addElement(String qualifiedName, String namespaceURI); + /** + * Adds a new Element node with the given qualified name and + * namespace URI to this branch and returns a reference to the new node. + * + * @param qualifiedName is the fully qualified name of the Element + * @param namespaceURI is the URI of the namespace to use + * @return the newly added Element node. + */ + Element addElement(String qualifiedName, String namespaceURI); - /** - * Removes the processing instruction for the given target if it exists - * - * @param target - * DOCUMENT ME! - * - * @return true if a processing instruction was removed else false - */ - boolean removeProcessingInstruction(String target); + /** + * Removes the processing instruction for the given target if it exists + * + * @param target DOCUMENT ME! + * @return true if a processing instruction was removed else false + */ + boolean removeProcessingInstruction(String target); - /** - * Adds the given Node or throws {@link IllegalAddException} - * if the given node is not of a valid type. This is a polymorphic method - * which will call the typesafe method for the node type such as - * add(Element) or add(Comment). - * - * @param node - * is the given node to add - */ - void add(Node node); + /** + * Adds the given Node or throws {@link IllegalAddException} + * if the given node is not of a valid type. This is a polymorphic method + * which will call the typesafe method for the node type such as + * add(Element) or add(Comment). + * + * @param node is the given node to add + */ + void add(Node node); - /** - * Adds the given Comment to this branch. If the given node - * already has a parent defined then an IllegalAddException - * will be thrown. - * - * @param comment - * is the comment to be added - */ - void add(Comment comment); + /** + * Adds the given Comment to this branch. If the given node + * already has a parent defined then an IllegalAddException + * will be thrown. + * + * @param comment is the comment to be added + */ + void add(Comment comment); - /** - * Adds the given Element to this branch. If the given node - * already has a parent defined then an IllegalAddException - * will be thrown. - * - * @param element - * is the element to be added - */ - void add(Element element); + /** + * Adds the given Element to this branch. If the given node + * already has a parent defined then an IllegalAddException + * will be thrown. + * + * @param element is the element to be added + */ + void add(Element element); - /** - * Adds the given ProcessingInstruction to this branch. If - * the given node already has a parent defined then an - * IllegalAddException will be thrown. - * - * @param pi - * is the processing instruction to be added - */ - void add(ProcessingInstruction pi); + /** + * Adds the given ProcessingInstruction to this branch. If + * the given node already has a parent defined then an + * IllegalAddException will be thrown. + * + * @param pi is the processing instruction to be added + */ + void add(ProcessingInstruction pi); - /** - * Removes the given Node if the node is an immediate child - * of this branch. If the given node is not an immediate child of this - * branch then the {@link Node#detach()}method should be used instead. This - * is a polymorphic method which will call the typesafe method for the node - * type such as remove(Element) or remove(Comment). - * - * @param node - * is the given node to be removed - * - * @return true if the node was removed - */ - boolean remove(Node node); + /** + * Removes the given Node if the node is an immediate child + * of this branch. If the given node is not an immediate child of this + * branch then the {@link Node#detach()}method should be used instead. This + * is a polymorphic method which will call the typesafe method for the node + * type such as remove(Element) or remove(Comment). + * + * @param node is the given node to be removed + * @return true if the node was removed + */ + boolean remove(Node node); - /** - * Removes the given Comment if the node is an immediate - * child of this branch. If the given node is not an immediate child of this - * branch then the {@link Node#detach()}method should be used instead. - * - * @param comment - * is the comment to be removed - * - * @return true if the comment was removed - */ - boolean remove(Comment comment); + /** + * Removes the given Comment if the node is an immediate + * child of this branch. If the given node is not an immediate child of this + * branch then the {@link Node#detach()}method should be used instead. + * + * @param comment is the comment to be removed + * @return true if the comment was removed + */ + boolean remove(Comment comment); - /** - * Removes the given Element if the node is an immediate - * child of this branch. If the given node is not an immediate child of this - * branch then the {@link Node#detach()}method should be used instead. - * - * @param element - * is the element to be removed - * - * @return true if the element was removed - */ - boolean remove(Element element); + /** + * Removes the given Element if the node is an immediate + * child of this branch. If the given node is not an immediate child of this + * branch then the {@link Node#detach()}method should be used instead. + * + * @param element is the element to be removed + * @return true if the element was removed + */ + boolean remove(Element element); - /** - * Removes the given ProcessingInstruction if the node is an - * immediate child of this branch. If the given node is not an immediate - * child of this branch then the {@link Node#detach()}method should be used - * instead. - * - * @param pi - * is the processing instruction to be removed - * - * @return true if the processing instruction was removed - */ - boolean remove(ProcessingInstruction pi); + /** + * Removes the given ProcessingInstruction if the node is an + * immediate child of this branch. If the given node is not an immediate + * child of this branch then the {@link Node#detach()}method should be used + * instead. + * + * @param pi is the processing instruction to be removed + * @return true if the processing instruction was removed + */ + boolean remove(ProcessingInstruction pi); - /** - * Puts all Text nodes in the full depth of the sub-tree - * underneath this Node, including attribute nodes, into a - * "normal" form where only structure (e.g., elements, comments, processing - * instructions, CDATA sections, and entity references) separates - * Text nodes, i.e., there are neither adjacent - * Text nodes nor empty Text nodes. This can - * be used to ensure that the DOM view of a document is the same as if it - * were saved and re-loaded, and is useful when operations (such as XPointer - * lookups) that depend on a particular document tree structure are to be - * used.In cases where the document contains CDATASections, - * the normalize operation alone may not be sufficient, since XPointers do - * not differentiate between Text nodes and - * CDATASection nodes. - * - * @since DOM Level 2 - */ - void normalize(); + /** + * Puts all Text nodes in the full depth of the sub-tree + * underneath this Node, including attribute nodes, into a + * "normal" form where only structure (e.g., elements, comments, processing + * instructions, CDATA sections, and entity references) separates + * Text nodes, i.e., there are neither adjacent + * Text nodes nor empty Text nodes. This can + * be used to ensure that the DOM view of a document is the same as if it + * were saved and re-loaded, and is useful when operations (such as XPointer + * lookups) that depend on a particular document tree structure are to be + * used.In cases where the document contains CDATASections, + * the normalize operation alone may not be sufficient, since XPointers do + * not differentiate between Text nodes and + * CDATASection nodes. + * + * @since DOM Level 2 + */ + void normalize(); } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/CDATA.java b/fine-org-dom4j/src/main/java/org/dom4j/CDATA.java index d6816106a..8db6aeedf 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/CDATA.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/CDATA.java @@ -8,13 +8,12 @@ package org.dom4j; /** - *

* CDATA defines an XML CDATA section. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ +@SuppressWarnings("unused") public interface CDATA extends CharacterData { } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/CharacterData.java b/fine-org-dom4j/src/main/java/org/dom4j/CharacterData.java index 1c5e9e73a..5d085ab2e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/CharacterData.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/CharacterData.java @@ -8,15 +8,14 @@ package org.dom4j; /** - *

* CharacterData is a marker interface for character based nodes * such as the CDATA,Comment and * Text nodes. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ +@SuppressWarnings("unused") public interface CharacterData extends Node { /** * Appends the given text to this nodes text value. Calling this method is diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Comment.java b/fine-org-dom4j/src/main/java/org/dom4j/Comment.java index 269853dc0..b06e4ad5d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Comment.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Comment.java @@ -8,13 +8,12 @@ package org.dom4j; /** - *

* Comment defines the behavior of an XML comment. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ +@SuppressWarnings("unused") public interface Comment extends CharacterData { } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Document.java b/fine-org-dom4j/src/main/java/org/dom4j/Document.java index dc3f928a7..efab81062 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Document.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Document.java @@ -7,18 +7,17 @@ package org.dom4j; -import java.util.Map; - import org.xml.sax.EntityResolver; +import java.util.Map; + /** - *

* Document defines an XML Document. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.14 $ */ +@SuppressWarnings("unused") public interface Document extends Branch { /** * Returns the root {@link Element}for this document. @@ -70,7 +69,7 @@ public interface Document extends Branch { * * @return this Document instance. */ - Document addProcessingInstruction(String target, Map data); + Document addProcessingInstruction(String target, Map data); /** * Adds a DOCTYPE declaration to this document @@ -124,15 +123,13 @@ public interface Document extends Branch { * when the Document was created in memory) or when the implementation does * not support this operation. * - *

* The way this encoding is retrieved also depends on the way the XML source * is parsed. For instance, if the SAXReader is used and if the underlying * XMLReader implementation support the * org.xml.sax.ext.Locator2 interface, the result returned by * this method is specified by the getEncoding() method of * that interface. - *

- * + * * @return The encoding of this document, as stated in the XML declaration, * or null if unknown. * diff --git a/fine-org-dom4j/src/main/java/org/dom4j/DocumentException.java b/fine-org-dom4j/src/main/java/org/dom4j/DocumentException.java index 2feb890be..2c7b5f027 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/DocumentException.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/DocumentException.java @@ -7,78 +7,32 @@ package org.dom4j; -import java.io.PrintStream; -import java.io.PrintWriter; - /** - *

- * DocumentException is a nested Exception which may be thrown - * during the processing of a DOM4J document. - *

- * + * DocumentException is a nested Exception which may be thrown during the processing of a DOM4J document. + * * @author James Strachan - * @version $Revision$ + * @author Filip Jirsák */ public class DocumentException extends Exception { - /** A wrapped Throwable */ - private Throwable nestedException; public DocumentException() { - super("Error occurred in DOM4J application."); } public DocumentException(String message) { super(message); } - public DocumentException(Throwable nestedException) { - super(nestedException.getMessage()); - this.nestedException = nestedException; + public DocumentException(String message, Throwable cause) { + super(message, cause); } - public DocumentException(String message, Throwable nestedException) { - super(message); - this.nestedException = nestedException; + public DocumentException(Throwable cause) { + super(cause); } + @Deprecated public Throwable getNestedException() { - return nestedException; - } - - public String getMessage() { - if (nestedException != null) { - return super.getMessage() + " Nested exception: " - + nestedException.getMessage(); - } else { - return super.getMessage(); - } - } - - public void printStackTrace() { - super.printStackTrace(); - - if (nestedException != null) { - System.err.print("Nested exception: "); - nestedException.printStackTrace(); - } - } - - public void printStackTrace(PrintStream out) { - super.printStackTrace(out); - - if (nestedException != null) { - out.println("Nested exception: "); - nestedException.printStackTrace(out); - } - } - - public void printStackTrace(PrintWriter writer) { - super.printStackTrace(writer); - - if (nestedException != null) { - writer.println("Nested exception: "); - nestedException.printStackTrace(writer); - } + return null; } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/DocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/DocumentFactory.java index 2571a3b40..9aaaa11cb 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/DocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/DocumentFactory.java @@ -32,28 +32,25 @@ import org.dom4j.xpath.XPathPattern; import org.jaxen.VariableContext; /** - *

* DocumentFactory is a collection of factory methods to allow * easy custom building of DOM4J trees. The default tree that is built uses a * doubly linked tree. - *

- * - *

+ * * The tree built allows full XPath expressions from anywhere on the tree. - *

- * + * * @author James Strachan */ +@SuppressWarnings("unused") public class DocumentFactory implements Serializable { - private static SingletonStrategy singleton = null; + private static SingletonStrategy singleton = null; protected transient QNameCache cache; - /** Default namespace prefix -> URI mappings for XPath expressions to use */ - private Map xpathNamespaceURIs; + /** Default namespace prefix → URI mappings for XPath expressions to use */ + private Map xpathNamespaceURIs; - private static SingletonStrategy createSingleton() { - SingletonStrategy result = null; + private static SingletonStrategy createSingleton() { + SingletonStrategy result; String documentFactoryClassName; try { @@ -67,10 +64,10 @@ public class DocumentFactory implements Serializable { String singletonClass = System.getProperty( "org.dom4j.DocumentFactory.singleton.strategy", "org.dom4j.util.SimpleSingleton"); - Class clazz = Class.forName(singletonClass); - result = (SingletonStrategy) clazz.newInstance(); + Class clazz = (Class) Class.forName(singletonClass); + result = clazz.newInstance(); } catch (Exception e) { - result = new SimpleSingleton(); + result = new SimpleSingleton(); } result.setSingletonClassName(documentFactoryClassName); @@ -83,18 +80,16 @@ public class DocumentFactory implements Serializable { } /** - *

* Access to singleton implementation of DocumentFactory which is used if no * DocumentFactory is specified when building using the standard builders. - *

- * + * * @return the default singleon instance */ public static synchronized DocumentFactory getInstance() { if (singleton == null) { singleton = createSingleton(); } - return (DocumentFactory) singleton.instance(); + return singleton.instance(); } // Factory methods @@ -121,10 +116,7 @@ public class DocumentFactory implements Serializable { // createDocument() method. Document answer = createDocument(); - if (answer instanceof AbstractDocument) { - ((AbstractDocument) answer).setXMLEncoding(encoding); - } - + answer.setXMLEncoding(encoding); return answer; } @@ -191,7 +183,7 @@ public class DocumentFactory implements Serializable { } public ProcessingInstruction createProcessingInstruction(String target, - Map data) { + Map data) { return new DefaultProcessingInstruction(target, data); } @@ -324,7 +316,7 @@ public class DocumentFactory implements Serializable { * * @return DOCUMENT ME! */ - public List getQNames() { + public List getQNames() { return cache.getQNames(); } @@ -337,7 +329,7 @@ public class DocumentFactory implements Serializable { * namespace URI. This value could well be null to indicate no * namespace URIs are being mapped. */ - public Map getXPathNamespaceURIs() { + public Map getXPathNamespaceURIs() { return xpathNamespaceURIs; } @@ -349,7 +341,7 @@ public class DocumentFactory implements Serializable { * @param namespaceURIs * DOCUMENT ME! */ - public void setXPathNamespaceURIs(Map namespaceURIs) { + public void setXPathNamespaceURIs(Map namespaceURIs) { this.xpathNamespaceURIs = namespaceURIs; } @@ -372,10 +364,10 @@ public class DocumentFactory implements Serializable { try { // I'll use the current class loader // that loaded me to avoid problems in J2EE and web apps - Class theClass = Class.forName(className, true, + Class theClass = (Class) Class.forName(className, true, DocumentFactory.class.getClassLoader()); - return (DocumentFactory) theClass.newInstance(); + return theClass.newInstance(); } catch (Throwable e) { System.out.println("WARNING: Cannot load DocumentFactory: " + className); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/DocumentHelper.java b/fine-org-dom4j/src/main/java/org/dom4j/DocumentHelper.java index 35f31bc1e..865a51a17 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/DocumentHelper.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/DocumentHelper.java @@ -18,16 +18,16 @@ import org.dom4j.rule.Pattern; import org.jaxen.VariableContext; import org.xml.sax.InputSource; +import org.xml.sax.SAXException; /** - *

* DocumentHelper is a collection of helper methods for using * DOM4J. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.26 $ */ +@SuppressWarnings("unused") public final class DocumentHelper { private DocumentHelper() { } @@ -89,7 +89,7 @@ public final class DocumentHelper { } public static ProcessingInstruction createProcessingInstruction(String pi, - Map data) { + Map data) { return getDocumentFactory().createProcessingInstruction(pi, data); } @@ -107,12 +107,12 @@ public final class DocumentHelper { * XPath XPath instance using the singleton {@link * DocumentFactory}. *

- * + * * @param xpathExpression * is the XPath expression to create - * + * * @return a new XPath instance - * + * * @throws InvalidXPathException * if the XPath expression is invalid */ @@ -127,14 +127,14 @@ public final class DocumentHelper { * XPath XPath instance using the singleton {@link * DocumentFactory}. *

- * + * * @param xpathExpression * is the XPath expression to create * @param context * is the variable context to use when evaluating the XPath - * + * * @return a new XPath instance - * + * * @throws InvalidXPathException * if the XPath expression is invalid */ @@ -150,10 +150,10 @@ public final class DocumentHelper { * filter expressions occur within XPath expressions such as * self::node()[ filterExpression ] *

- * + * * @param xpathFilterExpression * is the XPath filter expression to create - * + * * @return a new NodeFilter instance */ public static NodeFilter createXPathFilter(String xpathFilterExpression) { @@ -166,10 +166,10 @@ public final class DocumentHelper { * an XSLT style {@link Pattern}instance which can then be used in an XSLT * processing model. *

- * + * * @param xpathPattern * is the XPath pattern expression to create - * + * * @return a new Pattern instance */ public static Pattern createPattern(String xpathPattern) { @@ -182,15 +182,15 @@ public final class DocumentHelper { * {@link List}of {@link Node}instances appending all the results together * into a single list. *

- * + * * @param xpathFilterExpression * is the XPath filter expression to evaluate * @param nodes * is the list of nodes on which to evalute the XPath - * + * * @return the results of all the XPath evaluations as a single list */ - public static List selectNodes(String xpathFilterExpression, List nodes) { + public static List selectNodes(String xpathFilterExpression, List nodes) { XPath xpath = createXPath(xpathFilterExpression); return xpath.selectNodes(nodes); @@ -202,15 +202,15 @@ public final class DocumentHelper { * {@link List}of {@link Node}instances appending all the results together * into a single list. *

- * + * * @param xpathFilterExpression * is the XPath filter expression to evaluate * @param node * is the Node on which to evalute the XPath - * + * * @return the results of all the XPath evaluations as a single list */ - public static List selectNodes(String xpathFilterExpression, Node node) { + public static List selectNodes(String xpathFilterExpression, Node node) { XPath xpath = createXPath(xpathFilterExpression); return xpath.selectNodes(node); @@ -221,13 +221,13 @@ public final class DocumentHelper { * sort sorts the given List of Nodes using an XPath * expression as a {@link java.util.Comparator}. *

- * + * * @param list * is the list of Nodes to sort * @param xpathExpression * is the XPath expression used for comparison */ - public static void sort(List list, String xpathExpression) { + public static void sort(List list, String xpathExpression) { XPath xpath = createXPath(xpathExpression); xpath.sort(list); } @@ -238,7 +238,7 @@ public final class DocumentHelper { * expression as a {@link java.util.Comparator}and optionally removing * duplicates. *

- * + * * @param list * is the list of Nodes to sort * @param expression @@ -247,7 +247,7 @@ public final class DocumentHelper { * if true then duplicate values (using the sortXPath for * comparisions) will be removed from the List */ - public static void sort(List list, String expression, boolean distinct) { + public static void sort(List list, String expression, boolean distinct) { XPath xpath = createXPath(expression); xpath.sort(list, distinct); } @@ -257,25 +257,26 @@ public final class DocumentHelper { * parseText parses the given text as an XML document and * returns the newly created Document. *

- * + * + * Loading external DTD and entities is disabled (if it is possible) for security reasons. + * * @param text * the XML text to be parsed - * + * * @return a newly parsed Document - * + * * @throws DocumentException * if the document could not be parsed */ public static Document parseText(String text) throws DocumentException { - Document result = null; + SAXReader reader = SAXReader.createDefault(); - SAXReader reader = new SAXReader(); String encoding = getEncoding(text); InputSource source = new InputSource(new StringReader(text)); source.setEncoding(encoding); - result = reader.read(source); + Document result = reader.read(source); // if the XML parser doesn't provide a way to retrieve the encoding, // specify it manually @@ -322,14 +323,14 @@ public final class DocumentHelper { * get the first child <a> element, which would be created if it did * not exist, then the next child <b> and so on until finally a * <c> element is returned. - * + * * @param source * is the Element or Document to start navigating from * @param path * is a simple path expression, seperated by '/' which denotes * the path from the source to the resulting element such as * a/b/c - * + * * @return the first Element on the given path which either already existed * on the path or were created by this method. */ @@ -378,24 +379,24 @@ public final class DocumentHelper { * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided that the * following conditions are met: - * + * * 1. Redistributions of source code must retain copyright statements and * notices. Redistributions must also contain a copy of this document. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. The name "DOM4J" must not be used to endorse or promote products derived * from this Software without prior written permission of MetaStuff, Ltd. For * written permission, please contact dom4j-info@metastuff.com. - * + * * 4. Products derived from this Software may not be called "DOM4J" nor may * "DOM4J" appear in their names without prior written permission of MetaStuff, * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * + * * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * + * * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -407,6 +408,6 @@ public final class DocumentHelper { * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/DocumentType.java b/fine-org-dom4j/src/main/java/org/dom4j/DocumentType.java index d2c9f3cb2..aaea5eae0 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/DocumentType.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/DocumentType.java @@ -7,16 +7,17 @@ package org.dom4j; +import org.dom4j.dtd.Decl; + import java.util.List; /** - *

* DocumentType defines an XML DOCTYPE declaration. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ +@SuppressWarnings("unused") public interface DocumentType extends Node { /** * This method is the equivalent to the {@link #getName}method. It is added @@ -49,7 +50,7 @@ public interface DocumentType extends Node { * * @return DOCUMENT ME! */ - List getInternalDeclarations(); + List getInternalDeclarations(); /** * Sets the list of internal DTD declaration objects, defined in the @@ -58,7 +59,7 @@ public interface DocumentType extends Node { * @param declarations * DOCUMENT ME! */ - void setInternalDeclarations(List declarations); + void setInternalDeclarations(List declarations); /** * Returns a list of internal DTD declaration objects, defined in the @@ -66,7 +67,7 @@ public interface DocumentType extends Node { * * @return DOCUMENT ME! */ - List getExternalDeclarations(); + List getExternalDeclarations(); /** * Sets the list of internal DTD declaration objects, defined in the @@ -75,7 +76,7 @@ public interface DocumentType extends Node { * @param declarations * DOCUMENT ME! */ - void setExternalDeclarations(List declarations); + void setExternalDeclarations(List declarations); } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Element.java b/fine-org-dom4j/src/main/java/org/dom4j/Element.java index 56b446b13..9cf2738c3 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Element.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Element.java @@ -12,839 +12,682 @@ import java.util.List; import java.util.Map; /** - *

* Element interface defines an XML element. An element can have * declared namespaces, attributes, child nodes and textual content. - *

- * *

* Some of this interface is optional. Some implementations may be read-only and * not support being modified. Some implementations may not support the parent - * relationship and methods such as {@link #getParent}or {@link#getDocument}. - *

- * + * relationship and methods such as {@link #getParent}or {@link #getDocument}. + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.47 $ */ +@SuppressWarnings("unused") public interface Element extends Branch { - // Name and namespace related methods - // ------------------------------------------------------------------------- - - /** - *

- * Returns the QName of this element which represents the - * local name, the qualified name and the Namespace. - *

- * - * @return the QName associated with this element - */ - QName getQName(); - - /** - *

- * Sets the QName of this element which represents the local - * name, the qualified name and the Namespace. - *

- * - * @param qname - * is the QName to be associated with this element - */ - void setQName(QName qname); - - /** - *

- * Returns the Namespace of this element if one exists - * otherwise Namespace.NO_NAMESPACE is returned. - *

- * - * @return the Namespace associated with this element - */ - Namespace getNamespace(); - - /** - *

- * Returns the QName for the given qualified name, using the - * namespace URI in scope for the given prefix of the qualified name or the - * default namespace if the qualified name has no prefix. - *

- * - * @param qualifiedName - * DOCUMENT ME! - * - * @return the QName for the given qualified name - */ - QName getQName(String qualifiedName); - - /** - *

- * Returns the Namespace which is mapped to the given prefix - * or null if it could not be found. - *

- * - * @param prefix - * DOCUMENT ME! - * - * @return the Namespace associated with the given prefix - */ - Namespace getNamespaceForPrefix(String prefix); - - /** - *

- * Returns the Namespace which is mapped to the given URI or - * null if it could not be found. If there is more than one - * Namespace mapped to the URI, which of them will be - * returned is undetermined. - *

- * - * @param uri - * DOCUMENT ME! - * - * @return the Namespace associated with the given URI - */ - Namespace getNamespaceForURI(String uri); - - /** - *

- * Returns the all namespaces which are mapped to the given URI or an empty - * list if no such namespaces could be found. - *

- * - * @param uri - * DOCUMENT ME! - * - * @return the namespaces associated with the given URI - * - * @since 1.5 - */ - List getNamespacesForURI(String uri); - - /** - *

- * Returns the namespace prefix of this element if one exists otherwise an - * empty String is returned. - *

- * - * @return the prefix of the Namespace of this element or an - * empty String - */ - String getNamespacePrefix(); - - /** - *

- * Returns the URI mapped to the namespace of this element if one exists - * otherwise an empty String is returned. - *

- * - * @return the URI for the Namespace of this element or an - * empty String - */ - String getNamespaceURI(); - - /** - *

- * Returns the fully qualified name of this element. This will be the same - * as the value returned from {@link #getName}if this element has no - * namespace attached to this element or an expression of the form - * - *

-     * getNamespacePrefix() + ":" + getName()
-     * 
- * - * will be returned. - *

- * - * @return the fully qualified name of the element. - */ - String getQualifiedName(); - - /** - *

- * Returns any additional namespaces declarations for this element other - * than namespace returned via the {@link #getNamespace()}method. If no - * additional namespace declarations are present for this element then an - * empty list will be returned. The list is backed by the element such that - * changes to the list will be reflected in the element though the reverse - * is not the case. - *

- * - * @return a list of any additional namespace declarations. - */ - List additionalNamespaces(); - - /** - *

- * Returns all the namespaces declared by this element. If no namespaces are - * declared for this element then an empty list will be returned. The list - * is backed by the element such that changes to the list will be reflected - * in the element though the reverse is not the case. - *

- * - * @return a list of namespaces declared for this element. - */ - List declaredNamespaces(); - - // Builder methods - // ------------------------------------------------------------------------- - - /** - *

- * Adds the attribute value of the given local name. If an attribute already - * exists for the given name it will be replaced. Attributes with null - * values are silently ignored. If the value of the attribute is null then - * this method call will remove any attributes with the given name. - *

- * - * @param name - * is the name of the attribute whose value is to be added or - * updated - * @param value - * is the attribute's value - * - * @return this Element instance. - */ - Element addAttribute(String name, String value); - - /** - *

- * Adds the attribute value of the given fully qualified name. If an - * attribute already exists for the given name it will be replaced. - * Attributes with null values are silently ignored. If the value of the - * attribute is null then this method call will remove any attributes with - * the given name. - *

- * - * @param qName - * is the fully qualified name of the attribute whose value is to - * be added or updated - * @param value - * is the attribute's value - * - * @return this Element instance. - */ - Element addAttribute(QName qName, String value); - - /** - * Adds a new Comment node with the given text to this - * element. - * - * @param comment - * is the text for the Comment node. - * - * @return this Element instance. - */ - Element addComment(String comment); - - /** - * Adds a new CDATA node with the given text to this element. - * - * @param cdata - * is the text for the CDATA node. - * - * @return this Element instance. - */ - Element addCDATA(String cdata); - - /** - * Adds a new Entity node with the given name and text to - * this element and returns a reference to the new node. - * - * @param name - * is the name for the Entity node. - * @param text - * is the text for the Entity node. - * - * @return this Element instance. - */ - Element addEntity(String name, String text); - - /** - * Adds a namespace to this element for use by its child content - * - * @param prefix - * is the prefix to use, which should not be null or blank - * @param uri - * is the namespace URI - * - * @return this Element instance. - */ - Element addNamespace(String prefix, String uri); - - /** - * Adds a processing instruction for the given target - * - * @param target - * is the target of the processing instruction - * @param text - * is the textual data (key/value pairs) of the processing - * instruction - * - * @return this Element instance. - */ - Element addProcessingInstruction(String target, String text); - - /** - * Adds a processing instruction for the given target - * - * @param target - * is the target of the processing instruction - * @param data - * is a Map of the key / value pairs of the processing - * instruction - * - * @return this Element instance. - */ - Element addProcessingInstruction(String target, Map data); - - /** - * Adds a new Text node with the given text to this element. - * - * @param text - * is the text for the Text node. - * - * @return this Element instance. - */ - Element addText(String text); - - // Typesafe modifying methods - // ------------------------------------------------------------------------- - - /** - * Adds the given Attribute to this element. If the given - * node already has a parent defined then an - * IllegalAddException will be thrown. Attributes with null - * values are silently ignored. - * - *

- * If the value of the attribute is null then this method call will remove - * any attributes with the QName of this attribute. - *

- * - * @param attribute - * is the attribute to be added - */ - void add(Attribute attribute); - - /** - * Adds the given CDATA to this element. If the given node - * already has a parent defined then an IllegalAddException - * will be thrown. - * - * @param cdata - * is the CDATA to be added - */ - void add(CDATA cdata); - - /** - * Adds the given Entity to this element. If the given node - * already has a parent defined then an IllegalAddException - * will be thrown. - * - * @param entity - * is the entity to be added - */ - void add(Entity entity); - - /** - * Adds the given Text to this element. If the given node - * already has a parent defined then an IllegalAddException - * will be thrown. - * - * @param text - * is the text to be added - */ - void add(Text text); - - /** - * Adds the given Namespace to this element. If the given - * node already has a parent defined then an - * IllegalAddException will be thrown. - * - * @param namespace - * is the namespace to be added - */ - void add(Namespace namespace); - - /** - * Removes the given Attribute from this element. - * - * @param attribute - * is the attribute to be removed - * - * @return true if the attribute was removed - */ - boolean remove(Attribute attribute); - - /** - * Removes the given CDATA if the node is an immediate child - * of this element. If the given node is not an immediate child of this - * element then the {@link Node#detach()}method should be used instead. - * - * @param cdata - * is the CDATA to be removed - * - * @return true if the cdata was removed - */ - boolean remove(CDATA cdata); - - /** - * Removes the given Entity if the node is an immediate child - * of this element. If the given node is not an immediate child of this - * element then the {@link Node#detach()}method should be used instead. - * - * @param entity - * is the entity to be removed - * - * @return true if the entity was removed - */ - boolean remove(Entity entity); - - /** - * Removes the given Namespace if the node is an immediate - * child of this element. If the given node is not an immediate child of - * this element then the {@link Node#detach()}method should be used - * instead. - * - * @param namespace - * is the namespace to be removed - * - * @return true if the namespace was removed - */ - boolean remove(Namespace namespace); - - /** - * Removes the given Text if the node is an immediate child - * of this element. If the given node is not an immediate child of this - * element then the {@link Node#detach()}method should be used instead. - * - * @param text - * is the text to be removed - * - * @return true if the text was removed - */ - boolean remove(Text text); - - // Text methods - // ------------------------------------------------------------------------- - - /** - * Returns the text value of this element without recursing through child - * elements. This method iterates through all {@link Text},{@link CDATA} - * and {@link Entity}nodes that this element contains and appends the text - * values together. - * - * @return the textual content of this Element. Child elements are not - * navigated. This method does not return null; - */ - String getText(); - - /** - * DOCUMENT ME! - * - * @return the trimmed text value where whitespace is trimmed and normalised - * into single spaces. This method does not return null. - */ - String getTextTrim(); - - /** - * Returns the XPath string-value of this node. The behaviour of this method - * is defined in the XPath - * specification . This method returns the string-value of all the - * contained {@link Text},{@link CDATA},{@link Entity}and {@link - * Element} nodes all appended together. - * - * @return the text from all the child Text and Element nodes appended - * together. - */ - String getStringValue(); - - /** - * Accesses the data of this element which may implement data typing - * bindings such as XML Schema or Java Bean bindings or will return the same - * value as {@link #getText} - * - * @return DOCUMENT ME! - */ - Object getData(); - - /** - * Sets the data value of this element if this element supports data binding - * or calls {@link #setText}if it doesn't - * - * @param data - * DOCUMENT ME! - */ - void setData(Object data); - - // Attribute methods - // ------------------------------------------------------------------------- - - /** - *

- * Returns the {@link Attribute}instances this element contains as a backed - * {@link List}so that the attributes may be modified directly using the - * {@link List}interface. The List is backed by the - * Element so that changes to the list are reflected in the - * element and vice versa. - *

- * - * @return the attributes that this element contains as a List - */ - List attributes(); - - /** - * Sets the attributes that this element contains - * - * @param attributes - * DOCUMENT ME! - */ - void setAttributes(List attributes); - - /** - * DOCUMENT ME! - * - * @return the number of attributes this element contains - */ - int attributeCount(); - - /** - * DOCUMENT ME! - * - * @return an iterator over the attributes of this element - */ - Iterator attributeIterator(); - - /** - * Returns the attribute at the specified indexGets the - * - * @param index - * DOCUMENT ME! - * - * @return the attribute at the specified index where index >= 0 and - * index < number of attributes or throws an - * IndexOutOfBoundsException if the index is not within the - * allowable range - */ - Attribute attribute(int index); - - /** - * Returns the attribute with the given name - * - * @param name - * DOCUMENT ME! - * - * @return the attribute for the given local name in any namespace. If there - * are more than one attributes with the given local name in - * different namespaces then the first one is returned. - */ - Attribute attribute(String name); - - /** - * DOCUMENT ME! - * - * @param qName - * is the fully qualified name - * - * @return the attribute for the given fully qualified name or null if it - * could not be found. - */ - Attribute attribute(QName qName); - - /** - *

- * This returns the attribute value for the attribute with the given name - * and any namespace or null if there is no such attribute or the empty - * string if the attribute value is empty. - *

- * - * @param name - * is the name of the attribute value to be returnd - * - * @return the value of the attribute, null if the attribute does not exist - * or the empty string - */ - String attributeValue(String name); - - /** - *

- * This returns the attribute value for the attribute with the given name - * and any namespace or the default value if there is no such attribute - * value. - *

- * - * @param name - * is the name of the attribute value to be returnd - * @param defaultValue - * is the default value to be returned if the attribute has no - * value defined. - * - * @return the value of the attribute or the defaultValue if the attribute - * has no value defined. - */ - String attributeValue(String name, String defaultValue); - - /** - *

- * This returns the attribute value for the attribute with the given fully - * qualified name or null if there is no such attribute or the empty string - * if the attribute value is empty. - *

- * - * @param qName - * is the fully qualified name - * - * @return the value of the attribute, null if the attribute does not exist - * or the empty string - */ - String attributeValue(QName qName); - - /** - *

- * This returns the attribute value for the attribute with the given fully - * qualified name or the default value if there is no such attribute value. - *

- * - * @param qName - * is the fully qualified name - * @param defaultValue - * is the default value to be returned if the attribute has no - * value defined. - * - * @return the value of the attribute or the defaultValue if the attribute - * has no value defined. - */ - String attributeValue(QName qName, String defaultValue); - - /** - *

- * Sets the attribute value of the given local name. - *

- * - * @param name - * is the name of the attribute whose value is to be added or - * updated - * @param value - * is the attribute's value - * - * @deprecated As of version 0.5. Please use {@link - * #addAttribute(String,String)} instead. WILL BE REMOVED IN - * dom4j-1.6 !! - */ - void setAttributeValue(String name, String value); - - /** - *

- * Sets the attribute value of the given fully qualified name. - *

- * - * @param qName - * is the fully qualified name of the attribute whose value is to - * be added or updated - * @param value - * is the attribute's value - * - * @deprecated As of version 0.5. Please use {@link - * #addAttribute(QName,String)} instead. WILL BE REMOVED IN - * dom4j-1.6 !! - */ - void setAttributeValue(QName qName, String value); - - // Content methods - // ------------------------------------------------------------------------- - - /** - * Returns the first element for the given local name and any namespace. - * - * @param name - * DOCUMENT ME! - * - * @return the first element with the given local name - */ - Element element(String name); - - /** - * Returns the first element for the given fully qualified name. - * - * @param qName - * is the fully qualified name to search for - * - * @return the first element with the given fully qualified name - */ - Element element(QName qName); - - /** - *

- * Returns the elements contained in this element. If this element does not - * contain any elements then this method returns an empty list. The list is - * backed by the element such that changes to the list will be reflected in - * the element though the reverse is not the case. - *

- * - * @return a list of all the elements in this element. - */ - List elements(); - - /** - *

- * Returns the elements contained in this element with the given local name - * and any namespace. If no elements are found then this method returns an - * empty list. The list is backed by the element such that changes to the - * list will be reflected in the element though the reverse is not the case. - *

- * - * @param name - * DOCUMENT ME! - * - * @return a list of all the elements in this element for the given local - * name - */ - List elements(String name); - - /** - *

- * Returns the elements contained in this element with the given fully - * qualified name. If no elements are found then this method returns an - * empty list. The list is backed by the element such that changes to the - * list will be reflected in the element though the reverse is not the case. - *

- * - * @param qName - * is the fully qualified name to search for - * - * @return a list of all the elements in this element for the given fully - * qualified name. - */ - List elements(QName qName); - - /** - * Returns an iterator over all this elements child elements. - * - * @return an iterator over the contained elements - */ - Iterator elementIterator(); - - /** - * Returns an iterator over the elements contained in this element which - * match the given local name and any namespace. - * - * @param name - * DOCUMENT ME! - * - * @return an iterator over the contained elements matching the given local - * name - */ - Iterator elementIterator(String name); - - /** - * Returns an iterator over the elements contained in this element which - * match the given fully qualified name. - * - * @param qName - * is the fully qualified name to search for - * - * @return an iterator over the contained elements matching the given fully - * qualified name - */ - Iterator elementIterator(QName qName); - - // Helper methods - // ------------------------------------------------------------------------- - - /** - * DOCUMENT ME! - * - * @return true if this element is the root element of a document and this - * element supports the parent relationship else false. - */ - boolean isRootElement(); - - /** - *

- * Returns true if this Element has mixed content. Mixed - * content means that an element contains both textual data and child - * elements. - *

- * - * @return true if this element contains mixed content. - */ - boolean hasMixedContent(); - - /** - *

- * Returns true if this Element has text only content. - *

- * - * @return true if this element is empty or only contains text content. - */ - boolean isTextOnly(); - - /** - * Appends the attributes of the given element to me. This method behaves - * like the {@link java.util.Collection#addAll(java.util.Collection)} - * method. - * - * @param element - * is the element whose attributes will be added to me. - */ - void appendAttributes(Element element); - - /** - *

- * Creates a deep copy of this element The new element is detached from its - * parent, and getParent() on the clone will return null. - *

- * - * @return a new deep copy Element - */ - Element createCopy(); - - /** - *

- * Creates a deep copy of this element with the given local name The new - * element is detached from its parent, and getParent() on the clone will - * return null. - *

- * - * @param name - * DOCUMENT ME! - * - * @return a new deep copy Element - */ - Element createCopy(String name); - - /** - *

- * Creates a deep copy of this element with the given fully qualified name. - * The new element is detached from its parent, and getParent() on the clone - * will return null. - *

- * - * @param qName - * DOCUMENT ME! - * - * @return a new deep copy Element - */ - Element createCopy(QName qName); - - String elementText(String name); - - String elementText(QName qname); - - String elementTextTrim(String name); - - String elementTextTrim(QName qname); - - /** - * Returns a node at the given index suitable for an XPath result set. This - * means the resulting Node will either be null or it will support the - * parent relationship. - * - * @param index - * DOCUMENT ME! - * - * @return the Node for the given index which will support the parent - * relationship or null if there is not a node at the given index. - */ - Node getXPathResult(int index); + // Name and namespace related methods + // ------------------------------------------------------------------------- + + /** + * Returns the QName of this element which represents the + * local name, the qualified name and the Namespace. + * + * @return the QName associated with this element + */ + QName getQName(); + + /** + * Sets the QName of this element which represents the local + * name, the qualified name and the Namespace. + * + * @param qname is the QName to be associated with this element + */ + void setQName(QName qname); + + /** + * Returns the Namespace of this element if one exists + * otherwise Namespace.NO_NAMESPACE is returned. + * + * @return the Namespace associated with this element + */ + Namespace getNamespace(); + + /** + * Returns the QName for the given qualified name, using the + * namespace URI in scope for the given prefix of the qualified name or the + * default namespace if the qualified name has no prefix. + * + * @param qualifiedName DOCUMENT ME! + * @return the QName for the given qualified name + */ + QName getQName(String qualifiedName); + + /** + * Returns the Namespace which is mapped to the given prefix + * or null if it could not be found. + * + * @param prefix DOCUMENT ME! + * @return the Namespace associated with the given prefix + */ + Namespace getNamespaceForPrefix(String prefix); + + /** + * Returns the Namespace which is mapped to the given URI or + * null if it could not be found. If there is more than one + * Namespace mapped to the URI, which of them will be + * returned is undetermined. + * + * @param uri DOCUMENT ME! + * @return the Namespace associated with the given URI + */ + Namespace getNamespaceForURI(String uri); + + /** + * Returns the all namespaces which are mapped to the given URI or an empty + * list if no such namespaces could be found. + * + * @param uri DOCUMENT ME! + * @return the namespaces associated with the given URI + * @since 1.5 + */ + List getNamespacesForURI(String uri); + + /** + * Returns the namespace prefix of this element if one exists otherwise an + * empty String is returned. + * + * @return the prefix of the Namespace of this element or an + * empty String + */ + String getNamespacePrefix(); + + /** + * Returns the URI mapped to the namespace of this element if one exists + * otherwise an empty String is returned. + * + * @return the URI for the Namespace of this element or an + * empty String + */ + String getNamespaceURI(); + + /** + * Returns the fully qualified name of this element. This will be the same + * as the value returned from {@link #getName}if this element has no + * namespace attached to this element or an expression of the form + *
+	 * getNamespacePrefix() + ":" + getName()
+	 * 
+ * will be returned. + * + * @return the fully qualified name of the element. + */ + String getQualifiedName(); + + /** + * Returns any additional namespaces declarations for this element other + * than namespace returned via the {@link #getNamespace()}method. If no + * additional namespace declarations are present for this element then an + * empty list will be returned. The list is backed by the element such that + * changes to the list will be reflected in the element though the reverse + * is not the case. + * + * @return a list of any additional namespace declarations. + */ + List additionalNamespaces(); + + /** + * Returns all the namespaces declared by this element. If no namespaces are + * declared for this element then an empty list will be returned. The list + * is backed by the element such that changes to the list will be reflected + * in the element though the reverse is not the case. + * + * @return a list of namespaces declared for this element. + */ + List declaredNamespaces(); + + // Builder methods + // ------------------------------------------------------------------------- + + /** + * Adds the attribute value of the given local name. If an attribute already + * exists for the given name it will be replaced. Attributes with null + * values are silently ignored. If the value of the attribute is null then + * this method call will remove any attributes with the given name. + * + * @param name is the name of the attribute whose value is to be added or + * updated + * @param value is the attribute's value + * @return this Element instance. + */ + Element addAttribute(String name, String value); + + /** + * Adds the attribute value of the given fully qualified name. If an + * attribute already exists for the given name it will be replaced. + * Attributes with null values are silently ignored. If the value of the + * attribute is null then this method call will remove any attributes with + * the given name. + * + * @param qName is the fully qualified name of the attribute whose value is to + * be added or updated + * @param value is the attribute's value + * @return this Element instance. + */ + Element addAttribute(QName qName, String value); + + /** + * Adds a new Comment node with the given text to this + * element. + * + * @param comment is the text for the Comment node. + * @return this Element instance. + */ + Element addComment(String comment); + + /** + * Adds a new CDATA node with the given text to this element. + * + * @param cdata is the text for the CDATA node. + * @return this Element instance. + */ + Element addCDATA(String cdata); + + /** + * Adds a new Entity node with the given name and text to + * this element and returns a reference to the new node. + * + * @param name is the name for the Entity node. + * @param text is the text for the Entity node. + * @return this Element instance. + */ + Element addEntity(String name, String text); + + /** + * Adds a namespace to this element for use by its child content + * + * @param prefix is the prefix to use, which should not be null or blank + * @param uri is the namespace URI + * @return this Element instance. + */ + Element addNamespace(String prefix, String uri); + + /** + * Adds a processing instruction for the given target + * + * @param target is the target of the processing instruction + * @param text is the textual data (key/value pairs) of the processing + * instruction + * @return this Element instance. + */ + Element addProcessingInstruction(String target, String text); + + /** + * Adds a processing instruction for the given target + * + * @param target is the target of the processing instruction + * @param data is a Map of the key / value pairs of the processing + * instruction + * @return this Element instance. + */ + Element addProcessingInstruction(String target, Map data); + + /** + * Adds a new Text node with the given text to this element. + * + * @param text is the text for the Text node. + * @return this Element instance. + */ + Element addText(String text); + + // Typesafe modifying methods + // ------------------------------------------------------------------------- + + /** + * Adds the given Attribute to this element. If the given + * node already has a parent defined then an + * IllegalAddException will be thrown. Attributes with null + * values are silently ignored. + * + * If the value of the attribute is null then this method call will remove + * any attributes with the QName of this attribute. + * + * @param attribute is the attribute to be added + */ + void add(Attribute attribute); + + /** + * Adds the given CDATA to this element. If the given node + * already has a parent defined then an IllegalAddException + * will be thrown. + * + * @param cdata is the CDATA to be added + */ + void add(CDATA cdata); + + /** + * Adds the given Entity to this element. If the given node + * already has a parent defined then an IllegalAddException + * will be thrown. + * + * @param entity is the entity to be added + */ + void add(Entity entity); + + /** + * Adds the given Text to this element. If the given node + * already has a parent defined then an IllegalAddException + * will be thrown. + * + * @param text is the text to be added + */ + void add(Text text); + + /** + * Adds the given Namespace to this element. If the given + * node already has a parent defined then an + * IllegalAddException will be thrown. + * + * @param namespace is the namespace to be added + */ + void add(Namespace namespace); + + /** + * Removes the given Attribute from this element. + * + * @param attribute is the attribute to be removed + * @return true if the attribute was removed + */ + boolean remove(Attribute attribute); + + /** + * Removes the given CDATA if the node is an immediate child + * of this element. If the given node is not an immediate child of this + * element then the {@link Node#detach()}method should be used instead. + * + * @param cdata is the CDATA to be removed + * @return true if the cdata was removed + */ + boolean remove(CDATA cdata); + + /** + * Removes the given Entity if the node is an immediate child + * of this element. If the given node is not an immediate child of this + * element then the {@link Node#detach()}method should be used instead. + * + * @param entity is the entity to be removed + * @return true if the entity was removed + */ + boolean remove(Entity entity); + + /** + * Removes the given Namespace if the node is an immediate + * child of this element. If the given node is not an immediate child of + * this element then the {@link Node#detach()}method should be used + * instead. + * + * @param namespace is the namespace to be removed + * @return true if the namespace was removed + */ + boolean remove(Namespace namespace); + + /** + * Removes the given Text if the node is an immediate child + * of this element. If the given node is not an immediate child of this + * element then the {@link Node#detach()}method should be used instead. + * + * @param text is the text to be removed + * @return true if the text was removed + */ + boolean remove(Text text); + + // Text methods + // ------------------------------------------------------------------------- + + /** + * Returns the text value of this element without recursing through child + * elements. This method iterates through all {@link Text},{@link CDATA} + * and {@link Entity}nodes that this element contains and appends the text + * values together. + * + * @return the textual content of this Element. Child elements are not + * navigated. This method does not return null; + */ + String getText(); + + /** + * DOCUMENT ME! + * + * @return the trimmed text value where whitespace is trimmed and normalised + * into single spaces. This method does not return null. + */ + String getTextTrim(); + + /** + * Returns the XPath string-value of this node. The behaviour of this method + * is defined in the XPath + * specification . This method returns the string-value of all the + * contained {@link Text},{@link CDATA},{@link Entity}and {@link + * Element} nodes all appended together. + * + * @return the text from all the child Text and Element nodes appended + * together. + */ + String getStringValue(); + + /** + * Accesses the data of this element which may implement data typing + * bindings such as XML Schema or Java Bean bindings or will return the same + * value as {@link #getText} + * + * @return DOCUMENT ME! + */ + Object getData(); + + /** + * Sets the data value of this element if this element supports data binding + * or calls {@link #setText}if it doesn't + * + * @param data DOCUMENT ME! + */ + void setData(Object data); + + // Attribute methods + // ------------------------------------------------------------------------- + + /** + * Returns the {@link Attribute}instances this element contains as a backed + * {@link List}so that the attributes may be modified directly using the + * {@link List}interface. The List is backed by the + * Element so that changes to the list are reflected in the + * element and vice versa. + * + * @return the attributes that this element contains as a List + */ + List attributes(); + + /** + * Sets the attributes that this element contains + * + * @param attributes DOCUMENT ME! + */ + void setAttributes(List attributes); + + /** + * DOCUMENT ME! + * + * @return the number of attributes this element contains + */ + int attributeCount(); + + /** + * DOCUMENT ME! + * + * @return an iterator over the attributes of this element + */ + Iterator attributeIterator(); + + /** + * Returns the attribute at the specified indexGets the + * + * @param index DOCUMENT ME! + * @return the attribute at the specified index where index >= 0 and + * index < number of attributes or throws an + * IndexOutOfBoundsException if the index is not within the + * allowable range + */ + Attribute attribute(int index); + + /** + * Returns the attribute with the given name + * + * @param name DOCUMENT ME! + * @return the attribute for the given local name in any namespace. If there + * are more than one attributes with the given local name in + * different namespaces then the first one is returned. + */ + Attribute attribute(String name); + + /** + * DOCUMENT ME! + * + * @param qName is the fully qualified name + * @return the attribute for the given fully qualified name or null if it + * could not be found. + */ + Attribute attribute(QName qName); + + /** + * This returns the attribute value for the attribute with the given name + * and any namespace or null if there is no such attribute or the empty + * string if the attribute value is empty. + * + * @param name is the name of the attribute value to be returned + * @return the value of the attribute, null if the attribute does not exist + * or the empty string + */ + String attributeValue(String name); + + /** + * This returns the attribute value for the attribute with the given name + * and any namespace or the default value if there is no such attribute + * value. + * + * @param name is the name of the attribute value to be returned + * @param defaultValue is the default value to be returned if the attribute has no + * value defined. + * @return the value of the attribute or the defaultValue if the attribute + * has no value defined. + */ + String attributeValue(String name, String defaultValue); + + /** + * This returns the attribute value for the attribute with the given fully + * qualified name or null if there is no such attribute or the empty string + * if the attribute value is empty. + * + * @param qName is the fully qualified name + * @return the value of the attribute, null if the attribute does not exist + * or the empty string + */ + String attributeValue(QName qName); + + /** + * This returns the attribute value for the attribute with the given fully + * qualified name or the default value if there is no such attribute value. + * + * @param qName is the fully qualified name + * @param defaultValue is the default value to be returned if the attribute has no + * value defined. + * @return the value of the attribute or the defaultValue if the attribute + * has no value defined. + */ + String attributeValue(QName qName, String defaultValue); + + /** + * Sets the attribute value of the given local name. + * + * @param name is the name of the attribute whose value is to be added or + * updated + * @param value is the attribute's value + * @deprecated As of version 0.5. Please use {@link + * #addAttribute(String, String)} instead. WILL BE REMOVED IN + * dom4j-1.6 !! + */ + void setAttributeValue(String name, String value); + + /** + * Sets the attribute value of the given fully qualified name. + * + * @param qName is the fully qualified name of the attribute whose value is to + * be added or updated + * @param value is the attribute's value + * @deprecated As of version 0.5. Please use {@link + * #addAttribute(QName, String)} instead. WILL BE REMOVED IN + * dom4j-1.6 !! + */ + void setAttributeValue(QName qName, String value); + + // Content methods + // ------------------------------------------------------------------------- + + /** + * Returns the first element for the given local name and any namespace. + * + * @param name DOCUMENT ME! + * @return the first element with the given local name + */ + Element element(String name); + + /** + * Returns the first element for the given fully qualified name. + * + * @param qName is the fully qualified name to search for + * @return the first element with the given fully qualified name + */ + Element element(QName qName); + + /** + * Returns the elements contained in this element. If this element does not + * contain any elements then this method returns an empty list. The list is + * backed by the element such that changes to the list will be reflected in + * the element though the reverse is not the case. + * + * @return a list of all the elements in this element. + */ + List elements(); + + /** + * Returns the elements contained in this element with the given local name + * and any namespace. If no elements are found then this method returns an + * empty list. The list is backed by the element such that changes to the + * list will be reflected in the element though the reverse is not the case. + * + * @param name DOCUMENT ME! + * @return a list of all the elements in this element for the given local + * name + */ + List elements(String name); + + /** + * Returns the elements contained in this element with the given fully + * qualified name. If no elements are found then this method returns an + * empty list. The list is backed by the element such that changes to the + * list will be reflected in the element though the reverse is not the case. + * + * @param qName is the fully qualified name to search for + * @return a list of all the elements in this element for the given fully + * qualified name. + */ + List elements(QName qName); + + /** + * Returns an iterator over all this elements child elements. + * + * @return an iterator over the contained elements + */ + Iterator elementIterator(); + + /** + * Returns an iterator over the elements contained in this element which + * match the given local name and any namespace. + * + * @param name DOCUMENT ME! + * @return an iterator over the contained elements matching the given local + * name + */ + Iterator elementIterator(String name); + + /** + * Returns an iterator over the elements contained in this element which + * match the given fully qualified name. + * + * @param qName is the fully qualified name to search for + * @return an iterator over the contained elements matching the given fully + * qualified name + */ + Iterator elementIterator(QName qName); + + // Helper methods + // ------------------------------------------------------------------------- + + /** + * DOCUMENT ME! + * + * @return true if this element is the root element of a document and this + * element supports the parent relationship else false. + */ + boolean isRootElement(); + + /** + * Returns true if this Element has mixed content. Mixed + * content means that an element contains both textual data and child + * elements. + * + * @return true if this element contains mixed content. + */ + boolean hasMixedContent(); + + /** + * Returns true if this Element has text only content. + * + * @return true if this element is empty or only contains text content. + */ + boolean isTextOnly(); + + /** + * Appends the attributes of the given element to me. This method behaves + * like the {@link java.util.Collection#addAll(java.util.Collection)} + * method. + * + * @param element is the element whose attributes will be added to me. + */ + void appendAttributes(Element element); + + /** + * Creates a deep copy of this element The new element is detached from its + * parent, and getParent() on the clone will return null. + * + * @return a new deep copy Element + */ + Element createCopy(); + + /** + * Creates a deep copy of this element with the given local name The new + * element is detached from its parent, and getParent() on the clone will + * return null. + * + * @param name DOCUMENT ME! + * @return a new deep copy Element + */ + Element createCopy(String name); + + /** + * Creates a deep copy of this element with the given fully qualified name. + * The new element is detached from its parent, and getParent() on the clone + * will return null. + * + * @param qName DOCUMENT ME! + * @return a new deep copy Element + */ + Element createCopy(QName qName); + + String elementText(String name); + + String elementText(QName qname); + + String elementTextTrim(String name); + + String elementTextTrim(QName qname); + + /** + * Returns a node at the given index suitable for an XPath result set. This + * means the resulting Node will either be null or it will support the + * parent relationship. + * + * @param index DOCUMENT ME! + * @return the Node for the given index which will support the parent + * relationship or null if there is not a node at the given index. + */ + Node getXPathResult(int index); } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/ElementHandler.java b/fine-org-dom4j/src/main/java/org/dom4j/ElementHandler.java index a03bf85c0..f195891fc 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/ElementHandler.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/ElementHandler.java @@ -8,16 +8,15 @@ package org.dom4j; /** - *

* ElementHandler interface defines a handler of * Element objects. It is used primarily in event based * processing models such as for processing large XML documents as they are * being parsed rather than waiting until the whole document is parsed. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ +@SuppressWarnings("unused") public interface ElementHandler { /** * Called by an event based processor when an elements openning tag is diff --git a/fine-org-dom4j/src/main/java/org/dom4j/ElementPath.java b/fine-org-dom4j/src/main/java/org/dom4j/ElementPath.java index 2d8784c7f..8ddfdf6cc 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/ElementPath.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/ElementPath.java @@ -13,8 +13,9 @@ package org.dom4j; * primary use is to retrieve the current {@link Element}being processed. * * @author Dave White - * @version $Revision$ + * @version $Revision: 1.6 $ */ +@SuppressWarnings("unused") public interface ElementPath { /** * DOCUMENT ME! diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Entity.java b/fine-org-dom4j/src/main/java/org/dom4j/Entity.java index 7c851691e..e79a8e70e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Entity.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Entity.java @@ -8,13 +8,12 @@ package org.dom4j; /** - *

* Entity defines an XML entity. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ +@SuppressWarnings("unused") public interface Entity extends Node { } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/IllegalAddException.java b/fine-org-dom4j/src/main/java/org/dom4j/IllegalAddException.java index dca3852cf..ea716607e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/IllegalAddException.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/IllegalAddException.java @@ -8,12 +8,10 @@ package org.dom4j; /** - *

* IllegalAddException is thrown when a node is added incorrectly * to an {@link Element} - *

- * - * @version $Revision$ + * + * @version $Revision: 1.6 $ */ public class IllegalAddException extends IllegalArgumentException { public IllegalAddException(String reason) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/InvalidXPathException.java b/fine-org-dom4j/src/main/java/org/dom4j/InvalidXPathException.java index c02c15c55..5cfec688c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/InvalidXPathException.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/InvalidXPathException.java @@ -8,29 +8,19 @@ package org.dom4j; /** - *

* InvalidXPathException is thrown when an invalid XPath * expression is used to traverse an XML document - *

- * - * @version $Revision$ + * + * @version $Revision: 1.6 $ */ public class InvalidXPathException extends IllegalArgumentException { - /** The serialVersionUID. */ - private static final long serialVersionUID = 3257009869058881592L; - - public InvalidXPathException(String xpath) { + public InvalidXPathException(String xpath) { super("Invalid XPath expression: " + xpath); } public InvalidXPathException(String xpath, String reason) { super("Invalid XPath expression: " + xpath + " " + reason); } - - public InvalidXPathException(String xpath, Throwable t) { - super("Invalid XPath expression: '" + xpath - + "'. Caused by: " + t.getMessage()); - } } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Namespace.java b/fine-org-dom4j/src/main/java/org/dom4j/Namespace.java index 7f78978d5..8f948ad8d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Namespace.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Namespace.java @@ -12,13 +12,11 @@ import org.dom4j.tree.DefaultNamespace; import org.dom4j.tree.NamespaceCache; /** - *

* Namespace is a Flyweight Namespace that can be shared amongst * nodes. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.22 $ */ public class Namespace extends AbstractNode { /** Cache of Namespace instances */ @@ -51,6 +49,10 @@ public class Namespace extends AbstractNode { public Namespace(String prefix, String uri) { this.prefix = (prefix != null) ? prefix : ""; this.uri = (uri != null) ? uri : ""; + + if (!this.prefix.isEmpty()) { + QName.validateNCName(this.prefix); + } } /** diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Node.java b/fine-org-dom4j/src/main/java/org/dom4j/Node.java index fd11396cf..1cec5a3da 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Node.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Node.java @@ -12,26 +12,21 @@ import java.io.Writer; import java.util.List; /** - *

* Node defines the polymorphic behavior for all XML nodes in a * dom4j tree. - *

- * - *

+ * * A node can be output as its XML format, can be detached from its position in * a document and can have XPath expressions evaluated on itself. - *

- * - *

+ * * A node may optionally support the parent relationship and may be read only. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.31 $ * * @see #supportsParent * @see #isReadOnly */ +@SuppressWarnings("unused") public interface Node extends Cloneable { // W3C DOM complient node type codes @@ -381,7 +376,7 @@ public interface Node extends Cloneable { * @return the list of Node or String * instances depending on the XPath expression */ - List selectNodes(String xpathExpression); + List selectNodes(String xpathExpression); /** *

@@ -417,7 +412,7 @@ public interface Node extends Cloneable { * @return the list of Node instances sorted by the * comparisonXPathExpression */ - List selectNodes(String xpathExpression, String comparisonXPathExpression); + List selectNodes(String xpathExpression, String comparisonXPathExpression); /** *

@@ -438,7 +433,7 @@ public interface Node extends Cloneable { * @return the list of Node instances sorted by the * comparisonXPathExpression */ - List selectNodes(String xpathExpression, String comparisonXPathExpression, + List selectNodes(String xpathExpression, String comparisonXPathExpression, boolean removeDuplicates); /** diff --git a/fine-org-dom4j/src/main/java/org/dom4j/NodeFilter.java b/fine-org-dom4j/src/main/java/org/dom4j/NodeFilter.java index 936143323..a5091b9f7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/NodeFilter.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/NodeFilter.java @@ -8,15 +8,14 @@ package org.dom4j; /** - *

* NodeFilter defines the behavior for a filter or predicate * which acts on a DOM4J Node. Instances can be generated from an {@link * DocumentFactory}. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ +@SuppressWarnings("unused") public interface NodeFilter { /** *

diff --git a/fine-org-dom4j/src/main/java/org/dom4j/ProcessingInstruction.java b/fine-org-dom4j/src/main/java/org/dom4j/ProcessingInstruction.java index aaed0a46c..827ea7140 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/ProcessingInstruction.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/ProcessingInstruction.java @@ -10,16 +10,15 @@ package org.dom4j; import java.util.Map; /** - *

* ProcessingInstruction defines an XML processing instruction. * The {@link Node#getName}method will return the target of the PI and the * {@link Node#getText}method will return the data from all of the * instructions. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ +@SuppressWarnings("unused") public interface ProcessingInstruction extends Node { /** * This method is the equivalent to the {@link #getName}method. It is added @@ -63,11 +62,11 @@ public interface ProcessingInstruction extends Node { * * @return the values for this processing instruction as a Map */ - Map getValues(); + Map getValues(); void setValue(String name, String value); - void setValues(Map data); + void setValues(Map data); boolean removeValue(String name); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/QName.java b/fine-org-dom4j/src/main/java/org/dom4j/QName.java index 955c0d386..e9b2170e9 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/QName.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/QName.java @@ -11,40 +11,114 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.regex.Pattern; import org.dom4j.tree.QNameCache; import org.dom4j.util.SingletonStrategy; /** - *

* QName represents a qualified name value of an XML element or * attribute. It consists of a local name and a {@link Namespace}instance. This * object is immutable. - *

- * + * * @author James Strachan + * @author Filip Jirsák */ public class QName implements Serializable { /** The Singleton instance */ - private static SingletonStrategy singleton = null; + private static SingletonStrategy singleton = null; + + /** + * {@code NameStartChar} without colon. + * + *
NameStartChar	::=	":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
+ * + * @see XML 1.0 – 2.3 Common Syntactic Constructs + * @see XML 1.1 – 2.3 Common Syntactic Constructs + */ + private static final String NAME_START_CHAR = "_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD"; + + /** + * {@code NameChar} without colon. + * + *
NameChar	::=	NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
+ * + * @see XML 1.0 – 2.3 Common Syntactic Constructs + * @see XML 1.1 – 2.3 Common Syntactic Constructs + */ + private static final String NAME_CHAR = NAME_START_CHAR + "-.0-9\u00B7\u0300-\u036F\u203F-\u2040"; + + /** + * {@code NCName} + * + *
+     * NCName		::=	NCNameStartChar NCNameChar*	(An XML Name, minus the ":")
+     * NCNameChar	::=	NameChar -':'
+     * NCNameStartChar	::=	NameStartChar -':'
+     * 
+ * + * @see Namespaces in XML 1.0 – 4 Qualified Names + * @see Namespaces in XML 1.1 – 4 Qualified Names + */ + private static final String NCNAME = "["+NAME_START_CHAR+"]["+NAME_CHAR+"]*"; + + /** + * Regular expression for {@code Name} (with colon). + * + *
Name	::=	NameStartChar (NameChar)*
+ * + * @see XML 1.0 – 2.3 Common Syntactic Constructs + * @see XML 1.1 – 2.3 Common Syntactic Constructs + */ + private static final Pattern RE_NAME = Pattern.compile("[:"+NAME_START_CHAR+"][:"+NAME_CHAR+"]*"); + + /** + * Regular expression for {@code NCName}. + * + *
+     * NCName		::=	NCNameStartChar NCNameChar*	(An XML Name, minus the ":")
+     * NCNameChar	::=	NameChar -':'
+     * NCNameStartChar	::=	NameStartChar -':'
+     * 
+ * + * @see Namespaces in XML 1.0 – 4 Qualified Names + * @see Namespaces in XML 1.1 – 4 Qualified Names + */ + private static final Pattern RE_NCNAME = Pattern.compile(NCNAME); + + /** + * Regular expression for {@code QName}. + * + *
+     * QName		::=	PrefixedName | UnprefixedName
+     * PrefixedName	::=	Prefix ':' LocalPart
+     * UnprefixedName	::=	LocalPart
+     * Prefix		::=	NCName
+     * LocalPart	::=	NCName
+     * 
+ * + * @see Namespaces in XML 1.0 – 4 Qualified Names + * @see Namespaces in XML 1.1 – 4 Qualified Names + */ + private static final Pattern RE_QNAME = Pattern.compile("(?:"+NCNAME+":)?"+NCNAME); static { try { String defaultSingletonClass = "org.dom4j.util.SimpleSingleton"; - Class clazz = null; + Class clazz = null; try { String singletonClass = defaultSingletonClass; singletonClass = System.getProperty( "org.dom4j.QName.singleton.strategy", singletonClass); - clazz = Class.forName(singletonClass); + clazz = (Class) Class.forName(singletonClass); } catch (Exception exc1) { try { String singletonClass = defaultSingletonClass; - clazz = Class.forName(singletonClass); + clazz = (Class) Class.forName(singletonClass); } catch (Exception exc2) { } } - singleton = (SingletonStrategy) clazz.newInstance(); + singleton = clazz.newInstance(); singleton.setSingletonClassName(QNameCache.class.getName()); } catch (Exception exc3) { } @@ -73,6 +147,11 @@ public class QName implements Serializable { this.name = (name == null) ? "" : name; this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE : namespace; + if (this.namespace.equals(Namespace.NO_NAMESPACE)) { + validateName(this.name); + } else { + validateNCName(this.name); + } } public QName(String name, Namespace namespace, String qualifiedName) { @@ -80,6 +159,8 @@ public class QName implements Serializable { this.qualifiedName = qualifiedName; this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE : namespace; + validateNCName(this.name); + validateQName(this.qualifiedName); } public static QName get(String name) { @@ -231,28 +312,46 @@ public class QName implements Serializable { } private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + // We use writeObject() and not writeUTF() to minimize space // This allows for writing pointers to already written strings out.writeObject(namespace.getPrefix()); out.writeObject(namespace.getURI()); - - out.defaultWriteObject(); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + String prefix = (String) in.readObject(); String uri = (String) in.readObject(); - in.defaultReadObject(); - namespace = Namespace.get(prefix, uri); } private static QNameCache getCache() { - QNameCache cache = (QNameCache) singleton.instance(); + QNameCache cache = singleton.instance(); return cache; } + + private static void validateName(String name) { + if (!RE_NAME.matcher(name).matches()) { + throw new IllegalArgumentException(String.format("Illegal character in name: '%s'.", name)); + } + } + + protected static void validateNCName(String ncname) { + if (!RE_NCNAME.matcher(ncname).matches()) { + throw new IllegalArgumentException(String.format("Illegal character in local name: '%s'.", ncname)); + } + } + + private static void validateQName(String qname) { + if (!RE_QNAME.matcher(qname).matches()) { + throw new IllegalArgumentException(String.format("Illegal character in qualified name: '%s'.", qname)); + } + } } @@ -292,4 +391,4 @@ public class QName implements Serializable { * POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file + */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Text.java b/fine-org-dom4j/src/main/java/org/dom4j/Text.java index bc2e1b4a9..032bc5580 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Text.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Text.java @@ -8,13 +8,12 @@ package org.dom4j; /** - *

* Text defines an XML Text node. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ +@SuppressWarnings("unused") public interface Text extends CharacterData { } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/Visitor.java b/fine-org-dom4j/src/main/java/org/dom4j/Visitor.java index cc07df5bc..b09db4807 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/Visitor.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/Visitor.java @@ -8,24 +8,21 @@ package org.dom4j; /** - *

* Visitor is used to implement the Visitor * pattern in DOM4J. An object of this interface can be passed to a * Node which will then call its typesafe methods. Please refer * to the Gang of Four book of Design Patterns for more details on the * Visitor pattern. - *

- * - *

+ * * This site * has further discussion on design patterns and links to the GOF book. This link describes the * Visitor pattern in detail. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ +@SuppressWarnings("unused") public interface Visitor { /** *

diff --git a/fine-org-dom4j/src/main/java/org/dom4j/VisitorSupport.java b/fine-org-dom4j/src/main/java/org/dom4j/VisitorSupport.java index 3cfd7c235..220f6584e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/VisitorSupport.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/VisitorSupport.java @@ -8,14 +8,12 @@ package org.dom4j; /** - *

* VisitorSupport is an abstract base class which is useful for * implementation inheritence or when using anonymous inner classes to create * simple Visitor implementations. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.6 $ */ public abstract class VisitorSupport implements Visitor { public VisitorSupport() { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/XPath.java b/fine-org-dom4j/src/main/java/org/dom4j/XPath.java index 64de142be..bba823504 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/XPath.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/XPath.java @@ -7,304 +7,239 @@ package org.dom4j; -import java.util.List; -import java.util.Map; - import org.jaxen.FunctionContext; import org.jaxen.NamespaceContext; import org.jaxen.VariableContext; +import java.util.List; +import java.util.Map; + /** - *

* XPath represents an XPath expression after it has been parsed * from a String. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.20 $ */ +@SuppressWarnings("unused") public interface XPath extends NodeFilter { - /** - *

- * getText will return the textual version of the XPath - * expression. - *

- * - * @return the textual format of the XPath expression. - */ - String getText(); + /** + * getText will return the textual version of the XPath + * expression. + * + * @return the textual format of the XPath expression. + */ + String getText(); - /** - *

- * matches returns true if the given node matches the XPath - * expression. To be more precise when evaluating this XPath expression on - * the given node the result set must include the node. - *

- * - * @param node - * DOCUMENT ME! - * - * @return true if the given node matches this XPath expression - */ - boolean matches(Node node); + /** + * matches returns true if the given node matches the XPath + * expression. To be more precise when evaluating this XPath expression on + * the given node the result set must include the node. + * + * @param node DOCUMENT ME! + * @return true if the given node matches this XPath expression + */ + boolean matches(Node node); - /** - *

- * evaluate evaluates an XPath expression and returns the - * result as an {@link Object}. The object returned can either be a {@link - * List} of {@link Node}instances, a {@link Node}instance, a {@link - * String} or a {@link Number}instance depending on the XPath expression. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * - * @return the value of the XPath expression as a {@link List}of {@link - * Node} instances, a {@link Node}instance, a {@link String}or a - * {@link Number}instance depending on the XPath expression. - */ - Object evaluate(Object context); + /** + * evaluate evaluates an XPath expression and returns the + * result as an {@link Object}. The object returned can either be a {@link + * List} of {@link Node}instances, a {@link Node}instance, a {@link + * String} or a {@link Number}instance depending on the XPath expression. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @return the value of the XPath expression as a {@link List}of {@link + * Node} instances, a {@link Node}instance, a {@link String}or a + * {@link Number}instance depending on the XPath expression. + */ + Object evaluate(Object context); - /** - *

- * selectObject evaluates an XPath expression and returns the - * result as an {@link Object}. The object returned can either be a {@link - * List} of {@link Node}instances, a {@link Node}instance, a {@link - * String} or a {@link Number}instance depending on the XPath expression. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * - * @return the value of the XPath expression as a {@link List}of {@link - * Node} instances, a {@link Node}instance, a {@link String}or a - * {@link Number}instance depending on the XPath expression. - * - * @deprecated please use evaluate(Object) instead. WILL BE REMOVED IN - * dom4j-1.6 !! - */ - Object selectObject(Object context); + /** + * selectObject evaluates an XPath expression and returns the + * result as an {@link Object}. The object returned can either be a {@link + * List} of {@link Node}instances, a {@link Node}instance, a {@link + * String} or a {@link Number}instance depending on the XPath expression. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @return the value of the XPath expression as a {@link List}of {@link + * Node} instances, a {@link Node}instance, a {@link String}or a + * {@link Number}instance depending on the XPath expression. + * @deprecated please use evaluate(Object) instead. WILL BE REMOVED IN + * dom4j-1.6 !! + */ + Object selectObject(Object context); - /** - *

- * selectNodes performs this XPath expression on the given - * {@link Node}or {@link List}of {@link Node}s instances appending all - * the results together into a single list. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * - * @return the results of all the XPath evaluations as a single list - */ - List selectNodes(Object context); + /** + * selectNodes performs this XPath expression on the given + * {@link Node}or {@link List}of {@link Node}s instances appending all + * the results together into a single list. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @return the results of all the XPath evaluations as a single list + */ + List selectNodes(Object context); - /** - *

- * selectNodes evaluates the XPath expression on the given - * {@link Node}or {@link List}of {@link Node}s and returns the result as - * a List of Node s sorted by the sort XPath - * expression. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * @param sortXPath - * is the XPath expression to sort by - * - * @return a list of Node instances - */ - List selectNodes(Object context, XPath sortXPath); + /** + * selectNodes evaluates the XPath expression on the given + * {@link Node}or {@link List}of {@link Node}s and returns the result as + * a List of Node s sorted by the sort XPath + * expression. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @param sortXPath is the XPath expression to sort by + * @return a list of Node instances + */ + List selectNodes(Object context, XPath sortXPath); - /** - *

- * selectNodes evaluates the XPath expression on the given - * {@link Node}or {@link List}of {@link Node}s and returns the result as - * a List of Node s sorted by the sort XPath - * expression. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * @param sortXPath - * is the XPath expression to sort by - * @param distinct - * specifies whether or not duplicate values of the sort - * expression are allowed. If this parameter is true then only - * distinct sort expressions values are included in the result - * - * @return a list of Node instances - */ - List selectNodes(Object context, XPath sortXPath, boolean distinct); + /** + * selectNodes evaluates the XPath expression on the given + * {@link Node}or {@link List}of {@link Node}s and returns the result as + * a List of Node s sorted by the sort XPath + * expression. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @param sortXPath is the XPath expression to sort by + * @param distinct specifies whether or not duplicate values of the sort + * expression are allowed. If this parameter is true then only + * distinct sort expressions values are included in the result + * @return a list of Node instances + */ + List selectNodes(Object context, XPath sortXPath, boolean distinct); - /** - *

- * selectSingleNode evaluates this XPath expression on the - * given {@link Node}or {@link List}of {@link Node}s and returns the - * result as a single Node instance. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * - * @return a single matching Node instance - */ - Node selectSingleNode(Object context); + /** + * selectSingleNode evaluates this XPath expression on the + * given {@link Node}or {@link List}of {@link Node}s and returns the + * result as a single Node instance. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @return a single matching Node instance + */ + Node selectSingleNode(Object context); - /** - *

- * valueOf evaluates this XPath expression and returns the - * textual representation of the results using the XPath string() function. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * - * @return the string representation of the results of the XPath expression - */ - String valueOf(Object context); + /** + * valueOf evaluates this XPath expression and returns the + * textual representation of the results using the XPath string() function. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @return the string representation of the results of the XPath expression + */ + String valueOf(Object context); - /** - *

- * numberValueOf evaluates an XPath expression and returns - * the numeric value of the XPath expression if the XPath expression results - * is a number, or null if the result is not a number. - *

- * - * @param context - * is either a node or a list of nodes on which to evalute the - * XPath - * - * @return the numeric result of the XPath expression or null if the result - * is not a number. - */ - Number numberValueOf(Object context); + /** + * numberValueOf evaluates an XPath expression and returns + * the numeric value of the XPath expression if the XPath expression results + * is a number, or null if the result is not a number. + * + * @param context is either a node or a list of nodes on which to evalute the + * XPath + * @return the numeric result of the XPath expression or null if the result + * is not a number. + */ + Number numberValueOf(Object context); - /** - * Retrieve a boolean-value interpretation of this XPath expression when - * evaluated against a given context. - * - *

- * The boolean-value of the expression is determined per the - * boolean(..) core function as defined in the XPath - * specification. This means that an expression that selects zero nodes will - * return false, while an expression that selects - * one-or-more nodes will return true. - *

- * - * @param context - * The node, nodeset or Context object for evaluation. This value - * can be null - * - * @return The boolean-value interpretation of this expression. - * - * @since 1.5 - */ - boolean booleanValueOf(Object context); + /** + * Retrieve a boolean-value interpretation of this XPath expression when + * evaluated against a given context. + * + * The boolean-value of the expression is determined per the + * boolean(..) core function as defined in the XPath + * specification. This means that an expression that selects zero nodes will + * return false, while an expression that selects + * one-or-more nodes will return true. + * + * @param context The node, nodeset or Context object for evaluation. This value + * can be null + * @return The boolean-value interpretation of this expression. + * @since 1.5 + */ + boolean booleanValueOf(Object context); - /** - *

- * sort sorts the given List of Nodes using this XPath - * expression as a {@link java.util.Comparator}. - *

- * - * @param list - * is the list of Nodes to sort - */ - void sort(List list); + /** + * sort sorts the given List of Nodes using this XPath + * expression as a {@link java.util.Comparator}. + * + * @param list is the list of Nodes to sort + */ + void sort(List list); - /** - *

- * sort sorts the given List of Nodes using this XPath - * expression as a {@link java.util.Comparator}and optionally removing - * duplicates. - *

- * - * @param list - * is the list of Nodes to sort - * @param distinct - * if true then duplicate values (using the sortXPath for - * comparisions) will be removed from the List - */ - void sort(List list, boolean distinct); + /** + * sort sorts the given List of Nodes using this XPath + * expression as a {@link java.util.Comparator}and optionally removing + * duplicates. + * + * @param list is the list of Nodes to sort + * @param distinct if true then duplicate values (using the sortXPath for + * comparisions) will be removed from the List + */ + void sort(List list, boolean distinct); - /** - * DOCUMENT ME! - * - * @return the current function context - */ - FunctionContext getFunctionContext(); + /** + * DOCUMENT ME! + * + * @return the current function context + */ + FunctionContext getFunctionContext(); - /** - * Sets the function context to be used when evaluating XPath expressions - * - * @param functionContext - * DOCUMENT ME! - */ - void setFunctionContext(FunctionContext functionContext); + /** + * Sets the function context to be used when evaluating XPath expressions + * + * @param functionContext DOCUMENT ME! + */ + void setFunctionContext(FunctionContext functionContext); - /** - * DOCUMENT ME! - * - * @return the current namespace context - */ - NamespaceContext getNamespaceContext(); + /** + * DOCUMENT ME! + * + * @return the current namespace context + */ + NamespaceContext getNamespaceContext(); - /** - * Sets the namespace context to be used when evaluating XPath expressions - * - * @param namespaceContext - * DOCUMENT ME! - */ - void setNamespaceContext(NamespaceContext namespaceContext); + /** + * Sets the namespace context to be used when evaluating XPath expressions + * + * @param namespaceContext DOCUMENT ME! + */ + void setNamespaceContext(NamespaceContext namespaceContext); - /** - *

- * Sets the current NamespaceContext from a Map where the keys are the - * String namespace prefixes and the values are the namespace URIs. - *

- * - *

- * For example: - * - *

-     * Map uris = new HashMap();
-     * uris.put("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
-     * uris.put("m", "urn:xmethodsBabelFish");
-     * XPath xpath = document
-     *         .createXPath("SOAP-ENV:Envelope/SOAP-ENV:Body/m:BabelFish");
-     * xpath.setNamespaceURIs(uris);
-     * Node babelfish = xpath.selectSingleNode(document);
-     * 
- * - *

- * - * @param map - * the map containing the namespace mappings - */ - void setNamespaceURIs(Map map); + /** + * Sets the current NamespaceContext from a Map where the keys are the + * String namespace prefixes and the values are the namespace URIs. + * + * For example: + *
+	 * Map uris = new HashMap();
+	 * uris.put("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
+	 * uris.put("m", "urn:xmethodsBabelFish");
+	 * XPath xpath = document
+	 *         .createXPath("SOAP-ENV:Envelope/SOAP-ENV:Body/m:BabelFish");
+	 * xpath.setNamespaceURIs(uris);
+	 * Node babelfish = xpath.selectSingleNode(document);
+	 * 
+ * + * @param map the map containing the namespace mappings + */ + void setNamespaceURIs(Map map); - /** - * DOCUMENT ME! - * - * @return the current variable context - */ - VariableContext getVariableContext(); + /** + * DOCUMENT ME! + * + * @return the current variable context + */ + VariableContext getVariableContext(); - /** - * Sets the variable context to be used when evaluating XPath expressions - * - * @param variableContext - * DOCUMENT ME! - */ - void setVariableContext(VariableContext variableContext); + /** + * Sets the variable context to be used when evaluating XPath expressions + * + * @param variableContext DOCUMENT ME! + */ + void setVariableContext(VariableContext variableContext); } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/XPathException.java b/fine-org-dom4j/src/main/java/org/dom4j/XPathException.java index 795d1798f..7ef9e6e3d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/XPathException.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/XPathException.java @@ -8,13 +8,11 @@ package org.dom4j; /** - *

* XPathException is thrown when an exception occurs while * evaluating an XPath expression, usually due to some function throwing an * exception. - *

- * - * @version $Revision$ + * + * @version $Revision: 1.6 $ */ public class XPathException extends RuntimeException { /** The XPath expression that caused the exception */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttribute.java b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttribute.java index 6da437401..3ce01a892 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttribute.java @@ -18,7 +18,7 @@ import org.dom4j.tree.AbstractAttribute; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class BeanAttribute extends AbstractAttribute { /** The list of Bean attributes */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttributeList.java b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttributeList.java index 17e5a1982..46302fc64 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttributeList.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanAttributeList.java @@ -19,9 +19,9 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ -public class BeanAttributeList extends AbstractList { +public class BeanAttributeList extends AbstractList { /** The BeanElement that this */ private BeanElement parent; @@ -41,18 +41,18 @@ public class BeanAttributeList extends AbstractList { this.parent = parent; Object data = parent.getData(); - Class beanClass = (data != null) ? data.getClass() : null; + Class beanClass = (data != null) ? data.getClass() : null; this.beanMetaData = BeanMetaData.get(beanClass); this.attributes = new BeanAttribute[beanMetaData.attributeCount()]; } - public Attribute attribute(String name) { + public BeanAttribute attribute(String name) { int index = beanMetaData.getIndex(name); return attribute(index); } - public Attribute attribute(QName qname) { + public BeanAttribute attribute(QName qname) { int index = beanMetaData.getIndex(qname); return attribute(index); @@ -91,11 +91,12 @@ public class BeanAttributeList extends AbstractList { // List interface // ------------------------------------------------------------------------- + @Override public int size() { return attributes.length; } - public Object get(int index) { + public BeanAttribute get(int index) { BeanAttribute attribute = attributes[index]; if (attribute == null) { @@ -106,15 +107,15 @@ public class BeanAttributeList extends AbstractList { return attribute; } - public boolean add(Object object) { + public boolean add(BeanAttribute object) { throw new UnsupportedOperationException("add(Object) unsupported"); } - public void add(int index, Object object) { + public void add(int index, BeanAttribute object) { throw new UnsupportedOperationException("add(int,Object) unsupported"); } - public Object set(int index, Object object) { + public BeanAttribute set(int index, BeanAttribute object) { throw new UnsupportedOperationException("set(int,Object) unsupported"); } @@ -122,18 +123,15 @@ public class BeanAttributeList extends AbstractList { return false; } - public Object remove(int index) { - BeanAttribute attribute = (BeanAttribute) get(index); - Object oldValue = attribute.getValue(); + public BeanAttribute remove(int index) { + BeanAttribute attribute = get(index); attribute.setValue(null); - return oldValue; + return attribute; } public void clear() { - for (int i = 0, size = attributes.length; i < size; i++) { - BeanAttribute attribute = attributes[i]; - + for (BeanAttribute attribute : attributes) { if (attribute != null) { attribute.setValue(null); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanDocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanDocumentFactory.java index 5604a41bd..8c86f77aa 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanDocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanDocumentFactory.java @@ -26,7 +26,7 @@ import org.xml.sax.Attributes; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.14 $ */ public class BeanDocumentFactory extends DocumentFactory { /** The Singleton instance */ @@ -78,7 +78,7 @@ public class BeanDocumentFactory extends DocumentFactory { if (value != null) { try { - Class beanClass = Class.forName(value, true, + Class beanClass = Class.forName(value, true, BeanDocumentFactory.class.getClassLoader()); return beanClass.newInstance(); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanElement.java b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanElement.java index 05419bc32..95dd311af 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanElement.java @@ -25,7 +25,7 @@ import org.xml.sax.Attributes; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.15 $ */ public class BeanElement extends DefaultElement { /** The DocumentFactory instance used by default */ @@ -70,11 +70,11 @@ public class BeanElement extends DefaultElement { setAttributeList(null); } - public Attribute attribute(String name) { + public BeanAttribute attribute(String name) { return getBeanAttributeList().attribute(name); } - public Attribute attribute(QName qname) { + public BeanAttribute attribute(QName qname) { return getBeanAttributeList().attribute(qname); } @@ -98,7 +98,7 @@ public class BeanElement extends DefaultElement { return this; } - public void setAttributes(List attributes) { + public void setAttributes(List attributes) { throw new UnsupportedOperationException("Not implemented yet."); } @@ -109,7 +109,7 @@ public class BeanElement extends DefaultElement { if (className != null) { try { - Class beanClass = Class.forName(className, true, + Class beanClass = Class.forName(className, true, BeanElement.class.getClassLoader()); this.setData(beanClass.newInstance()); @@ -147,11 +147,11 @@ public class BeanElement extends DefaultElement { * * @return DOCUMENT ME! */ - protected List createAttributeList() { + protected List createAttributeList() { return new BeanAttributeList(this); } - protected List createAttributeList(int size) { + protected List createAttributeList(int size) { return new BeanAttributeList(this); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanMetaData.java b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanMetaData.java index 0a6a8da78..4bb3f20f3 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanMetaData.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/bean/BeanMetaData.java @@ -24,20 +24,20 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class BeanMetaData { /** Empty arguments for reflection calls */ protected static final Object[] NULL_ARGS = {}; /** Singleton cache */ - private static Map singletonCache = new HashMap(); + private static Map, BeanMetaData> singletonCache = new HashMap, BeanMetaData>(); private static final DocumentFactory DOCUMENT_FACTORY = BeanDocumentFactory .getInstance(); /** The class of the bean */ - private Class beanClass; + private Class beanClass; /** Property descriptors for the bean */ private PropertyDescriptor[] propertyDescriptors; @@ -51,10 +51,12 @@ public class BeanMetaData { /** Write methods used for setting properties */ private Method[] writeMethods; - /** Index of names and QNames to indices */ - private Map nameMap = new HashMap(); + /** Index of names and QNames to indices + * Keys are type of QName and String + */ + private Map nameMap = new HashMap(); - public BeanMetaData(Class beanClass) { + public BeanMetaData(Class beanClass) { this.beanClass = beanClass; if (beanClass != null) { @@ -83,9 +85,8 @@ public class BeanMetaData { readMethods[i] = propertyDescriptor.getReadMethod(); writeMethods[i] = propertyDescriptor.getWriteMethod(); - Integer index = new Integer(i); - nameMap.put(name, index); - nameMap.put(qName, index); + nameMap.put(name, i); + nameMap.put(qName, i); } } @@ -97,8 +98,8 @@ public class BeanMetaData { * * @return DOCUMENT ME! */ - public static BeanMetaData get(Class beanClass) { - BeanMetaData answer = (BeanMetaData) singletonCache.get(beanClass); + public static BeanMetaData get(Class beanClass) { + BeanMetaData answer = singletonCache.get(beanClass); if (answer == null) { answer = new BeanMetaData(beanClass); @@ -126,15 +127,15 @@ public class BeanMetaData { } public int getIndex(String name) { - Integer index = (Integer) nameMap.get(name); + Integer index = nameMap.get(name); - return (index != null) ? index.intValue() : (-1); + return (index != null) ? index : (-1); } public int getIndex(QName qName) { - Integer index = (Integer) nameMap.get(qName); + Integer index = nameMap.get(qName); - return (index != null) ? index.intValue() : (-1); + return (index != null) ? index : (-1); } public Object getData(int index, Object bean) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/bean/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/bean/package-info.java new file mode 100644 index 000000000..d7773e65a --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/bean/package-info.java @@ -0,0 +1,4 @@ +/** + * An implementation of the dom4j API which allows JavaBeans to be used to store and retrieve attribute values from Element. + */ +package org.dom4j.bean; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/bean/package.html b/fine-org-dom4j/src/main/java/org/dom4j/bean/package.html deleted file mode 100644 index 3e446e455..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/bean/package.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -

An implementation of the dom4j API which allows JavaBeans to be used to - store and retrieve attribute values from Element.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeAttribute.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeAttribute.java index 103cf9405..790e1c7b0 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeAttribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeAttribute.java @@ -27,7 +27,7 @@ import org.relaxng.datatype.ValidationContext; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class DatatypeAttribute extends AbstractAttribute implements SerializationContext, ValidationContext { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeDocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeDocumentFactory.java index f66cdb1b1..76ef4f87b 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeDocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeDocumentFactory.java @@ -26,7 +26,7 @@ import org.xml.sax.InputSource; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class DatatypeDocumentFactory extends DocumentFactory { // XXXX: I don't think interning of QNames is necessary diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElement.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElement.java index b2688478b..0b87ff54e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElement.java @@ -28,7 +28,7 @@ import org.relaxng.datatype.ValidationContext; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class DatatypeElement extends DefaultElement implements SerializationContext, ValidationContext { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElementFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElementFactory.java index 6c9df4c0d..327fb4f5c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElementFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/DatatypeElementFactory.java @@ -25,7 +25,7 @@ import org.dom4j.QName; * * @author James Strachan * @author Yuxin Ruan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class DatatypeElementFactory extends DocumentFactory { private QName elementQName; @@ -34,13 +34,13 @@ public class DatatypeElementFactory extends DocumentFactory { * Cache of XSDatatype instances per Attribute * QName */ - private Map attributeXSDatatypes = new HashMap(); + private Map attributeXSDatatypes = new HashMap(); /** * Cache of XSDatatype instances per child Element * QName */ - private Map childrenXSDatatypes = new HashMap(); + private Map childrenXSDatatypes = new HashMap(); public DatatypeElementFactory(QName elementQName) { this.elementQName = elementQName; @@ -65,7 +65,7 @@ public class DatatypeElementFactory extends DocumentFactory { * QName */ public XSDatatype getAttributeXSDatatype(QName attributeQName) { - return (XSDatatype) attributeXSDatatypes.get(attributeQName); + return attributeXSDatatypes.get(attributeQName); } /** @@ -91,7 +91,7 @@ public class DatatypeElementFactory extends DocumentFactory { * Element QName */ public XSDatatype getChildElementXSDatatype(QName qname) { - return (XSDatatype) childrenXSDatatypes.get(qname); + return childrenXSDatatypes.get(qname); } public void setChildElementXSDatatype(QName qname, XSDatatype dataType) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/InvalidSchemaException.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/InvalidSchemaException.java index f099cd30b..0aef4f084 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/InvalidSchemaException.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/InvalidSchemaException.java @@ -13,7 +13,7 @@ package org.dom4j.datatype; * document is used *

* - * @version $Revision$ + * @version $Revision: 1.6 $ */ public class InvalidSchemaException extends IllegalArgumentException { public InvalidSchemaException(String reason) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/NamedTypeResolver.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/NamedTypeResolver.java index 642976f31..f0b18f175 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/NamedTypeResolver.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/NamedTypeResolver.java @@ -23,16 +23,16 @@ import org.dom4j.QName; *

* * @author Yuxin Ruan - * @version $Revision$ + * @version $Revision: 1.8 $ */ class NamedTypeResolver { - protected Map complexTypeMap = new HashMap(); + protected Map complexTypeMap = new HashMap(); - protected Map simpleTypeMap = new HashMap(); + protected Map simpleTypeMap = new HashMap(); - protected Map typedElementMap = new HashMap(); + protected Map typedElementMap = new HashMap(); - protected Map elementFactoryMap = new HashMap(); + protected Map elementFactoryMap = new HashMap(); protected DocumentFactory documentFactory; @@ -55,10 +55,7 @@ class NamedTypeResolver { } void resolveElementTypes() { - Iterator iterator = typedElementMap.keySet().iterator(); - - while (iterator.hasNext()) { - Element element = (Element) iterator.next(); + for (Element element : typedElementMap.keySet()) { QName elementQName = getQNameOfSchemaElement(element); QName type = (QName) typedElementMap.get(element); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/SchemaParser.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/SchemaParser.java index d5a496f14..ab299d82c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/SchemaParser.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/SchemaParser.java @@ -37,7 +37,7 @@ import org.xml.sax.InputSource; * * @author James Strachan * @author Yuxin Ruan - * @version $Revision$ + * @version $Revision: 1.19 $ */ public class SchemaParser { private static final Namespace XSD_NAMESPACE = Namespace.get("xsd", @@ -76,7 +76,7 @@ public class SchemaParser { * Cache of XSDatatype instances loaded or created during * this build */ - private Map dataTypeCache = new HashMap(); + private Map dataTypeCache = new HashMap(); /** NamedTypeResolver */ private NamedTypeResolver namedTypeResolver; @@ -113,11 +113,7 @@ public class SchemaParser { Element root = schemaDocument.getRootElement(); if (root != null) { - // handle schema includes - Iterator includeIter = root.elementIterator(XSD_INCLUDE); - - while (includeIter.hasNext()) { - Element includeElement = (Element) includeIter.next(); + for (Element includeElement : root.elements(XSD_INCLUDE)) { String inclSchemaInstanceURI = includeElement .attributeValue("schemaLocation"); EntityResolver resolver = schemaDocument.getEntityResolver(); @@ -151,24 +147,18 @@ public class SchemaParser { } // handle elements - Iterator iter = root.elementIterator(XSD_ELEMENT); - - while (iter.hasNext()) { - onDatatypeElement((Element) iter.next(), documentFactory); + for (Element element : root.elements(XSD_ELEMENT)) { + onDatatypeElement(element, documentFactory); } // handle named simple types - iter = root.elementIterator(XSD_SIMPLETYPE); - - while (iter.hasNext()) { - onNamedSchemaSimpleType((Element) iter.next()); + for (Element element : root.elements(XSD_SIMPLETYPE)) { + onNamedSchemaSimpleType(element); } // hanlde named complex types - iter = root.elementIterator(XSD_COMPLEXTYPE); - - while (iter.hasNext()) { - onNamedSchemaComplexType((Element) iter.next()); + for (Element element : root.elements(XSD_COMPLEXTYPE)) { + onNamedSchemaComplexType(element); } namedTypeResolver.resolveNamedTypes(); @@ -190,15 +180,19 @@ public class SchemaParser { DocumentFactory parentFactory) { String name = xsdElement.attributeValue("name"); String type = xsdElement.attributeValue("type"); - QName qname = getQName(name); - DatatypeElementFactory factory = getDatatypeElementFactory(qname); + QName qname = null; + DatatypeElementFactory factory = null; + if (name != null) { + qname = getQName(name); + factory = getDatatypeElementFactory(qname); + } if (type != null) { // register type with this element name XSDatatype dataType = getTypeByName(type); - if (dataType != null) { + if (dataType != null && factory != null) { factory.setChildElementXSDatatype(qname, dataType); } else { QName typeQName = getQName(type); @@ -215,24 +209,25 @@ public class SchemaParser { if (xsdSimpleType != null) { XSDatatype dataType = loadXSDatatypeFromSimpleType(xsdSimpleType); - if (dataType != null) { + if (dataType != null && factory != null) { factory.setChildElementXSDatatype(qname, dataType); } } Element schemaComplexType = xsdElement.element(XSD_COMPLEXTYPE); - if (schemaComplexType != null) { + if (schemaComplexType != null && factory != null) { onSchemaComplexType(schemaComplexType, factory); } - Iterator iter = xsdElement.elementIterator(XSD_ATTRIBUTE); - - if (iter.hasNext()) { - do { - onDatatypeAttribute(xsdElement, factory, (Element) iter - .next()); - } while (iter.hasNext()); + if (factory != null) { + Iterator iter = xsdElement.elementIterator(XSD_ATTRIBUTE); + if (iter.hasNext()) { + do { + onDatatypeAttribute(xsdElement, factory, iter + .next()); + } while (iter.hasNext()); + } } } @@ -268,10 +263,10 @@ public class SchemaParser { */ private void onSchemaComplexType(Element schemaComplexType, DatatypeElementFactory elementFactory) { - Iterator iter = schemaComplexType.elementIterator(XSD_ATTRIBUTE); + Iterator iter = schemaComplexType.elementIterator(XSD_ATTRIBUTE); while (iter.hasNext()) { - Element xsdAttribute = (Element) iter.next(); + Element xsdAttribute = iter.next(); String name = xsdAttribute.attributeValue("name"); QName qname = getQName(name); @@ -308,10 +303,10 @@ public class SchemaParser { } private void onChildElements(Element element, DatatypeElementFactory fact) { - Iterator iter = element.elementIterator(XSD_ELEMENT); + Iterator iter = element.elementIterator(XSD_ELEMENT); while (iter.hasNext()) { - Element xsdElement = (Element) iter.next(); + Element xsdElement = iter.next(); onDatatypeElement(xsdElement, fact); } } @@ -355,7 +350,7 @@ public class SchemaParser { */ private XSDatatype dataTypeForXsdAttribute(Element xsdAttribute) { String type = xsdAttribute.attributeValue("type"); - XSDatatype dataType = null; + XSDatatype dataType; if (type != null) { dataType = getTypeByName(type); @@ -459,9 +454,9 @@ public class SchemaParser { ValidationContext context = null; try { - for (Iterator iter = xsdRestriction.elementIterator(); iter + for (Iterator iter = xsdRestriction.elementIterator(); iter .hasNext();) { - Element element = (Element) iter.next(); + Element element = iter.next(); String name = element.getName(); String value = element.attributeValue("value"); boolean fixed = AttributeHelper.booleanValue(element, "fixed"); @@ -504,7 +499,7 @@ public class SchemaParser { } private XSDatatype getTypeByName(String type) { - XSDatatype dataType = (XSDatatype) dataTypeCache.get(type); + XSDatatype dataType = dataTypeCache.get(type); if (dataType == null) { // first check to see if it is a built-in type @@ -530,7 +525,7 @@ public class SchemaParser { if (dataType == null) { // it's no built-in type, maybe it's a type we defined ourself QName typeQName = getQName(type); - dataType = (XSDatatype) namedTypeResolver.simpleTypeMap + dataType = namedTypeResolver.simpleTypeMap .get(typeQName); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/datatype/package-info.java new file mode 100644 index 000000000..d64979e49 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/datatype/package-info.java @@ -0,0 +1,4 @@ +/** + * An implementation of the dom4j API which supports the XML Schema Data Types specification. + */ +package org.dom4j.datatype; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/datatype/package.html b/fine-org-dom4j/src/main/java/org/dom4j/datatype/package.html deleted file mode 100644 index 2ac0c0953..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/datatype/package.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -

An implementation of the dom4j API which supports the - XML Schema Data Types specification.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttribute.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttribute.java index a35c9ac86..e48fd8aa5 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttribute.java @@ -10,13 +10,7 @@ package org.dom4j.dom; import org.dom4j.Element; import org.dom4j.QName; import org.dom4j.tree.DefaultAttribute; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.TypeInfo; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; /** *

@@ -25,7 +19,7 @@ import org.w3c.dom.UserDataHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.14 $ */ public class DOMAttribute extends DefaultAttribute implements org.w3c.dom.Attr { public DOMAttribute(QName qname) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttributeNodeMap.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttributeNodeMap.java index ff5289fcd..29e61e9c7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttributeNodeMap.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMAttributeNodeMap.java @@ -18,7 +18,7 @@ import org.w3c.dom.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ public class DOMAttributeNodeMap implements org.w3c.dom.NamedNodeMap { private DOMElement element; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMCDATA.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMCDATA.java index 9c26a3381..2ccc0732d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMCDATA.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMCDATA.java @@ -10,13 +10,7 @@ package org.dom4j.dom; import org.dom4j.CDATA; import org.dom4j.Element; import org.dom4j.tree.DefaultCDATA; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; /** *

@@ -25,7 +19,7 @@ import org.w3c.dom.UserDataHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public class DOMCDATA extends DefaultCDATA implements org.w3c.dom.CDATASection { public DOMCDATA(String text) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMComment.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMComment.java index 11d46f121..3208927fd 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMComment.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMComment.java @@ -9,12 +9,7 @@ package org.dom4j.dom; import org.dom4j.Element; import org.dom4j.tree.DefaultComment; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; /** *

@@ -22,7 +17,7 @@ import org.w3c.dom.UserDataHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public class DOMComment extends DefaultComment implements org.w3c.dom.Comment { public DOMComment(String text) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocument.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocument.java index 16ac34ad6..12b477a99 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocument.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocument.java @@ -7,20 +7,16 @@ package org.dom4j.dom; -import org.dom4j.DocumentFactory; -import org.dom4j.QName; +import org.dom4j.*; import org.dom4j.tree.DefaultDocument; -import org.w3c.dom.Attr; -import org.w3c.dom.CDATASection; -import org.w3c.dom.DOMConfiguration; -import org.w3c.dom.DOMException; +import org.w3c.dom.*; +import org.w3c.dom.Comment; import org.w3c.dom.Document; -import org.w3c.dom.EntityReference; -import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; import org.w3c.dom.Node; -import org.w3c.dom.NodeList; import org.w3c.dom.ProcessingInstruction; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.Text; import java.util.ArrayList; @@ -31,7 +27,7 @@ import java.util.ArrayList; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.17 $ */ public class DOMDocument extends DefaultDocument implements Document { /** The DocumentFactory instance used by default */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentFactory.java index 5030bd1da..570c9ba38 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentFactory.java @@ -7,18 +7,7 @@ package org.dom4j.dom; -import org.dom4j.Attribute; -import org.dom4j.CDATA; -import org.dom4j.Comment; -import org.dom4j.Document; -import org.dom4j.DocumentFactory; -import org.dom4j.DocumentType; -import org.dom4j.Element; -import org.dom4j.Entity; -import org.dom4j.Namespace; -import org.dom4j.ProcessingInstruction; -import org.dom4j.QName; -import org.dom4j.Text; +import org.dom4j.*; import org.dom4j.util.SingletonStrategy; import org.w3c.dom.DOMException; @@ -31,32 +20,32 @@ import java.util.Map; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.21 $ */ public class DOMDocumentFactory extends DocumentFactory implements org.w3c.dom.DOMImplementation { /** The Singleton instance */ - private static SingletonStrategy singleton = null; + private static SingletonStrategy singleton = null; static { try { String defaultSingletonClass = "org.dom4j.util.SimpleSingleton"; - Class clazz = null; + Class clazz = null; try { String singletonClass = defaultSingletonClass; singletonClass = System.getProperty( "org.dom4j.dom.DOMDocumentFactory.singleton.strategy", singletonClass); - clazz = Class.forName(singletonClass); + clazz = (Class) Class.forName(singletonClass); } catch (Exception exc1) { try { String singletonClass = defaultSingletonClass; - clazz = Class.forName(singletonClass); + clazz = (Class) Class.forName(singletonClass); } catch (Exception exc2) { } } - singleton = (SingletonStrategy) clazz.newInstance(); + singleton = clazz.newInstance(); singleton.setSingletonClassName(DOMDocumentFactory.class.getName()); } catch (Exception exc3) { } @@ -66,12 +55,11 @@ public class DOMDocumentFactory extends DocumentFactory implements *

* Access to the singleton instance of this factory. *

- * + * * @return the default singleon instance */ public static DocumentFactory getInstance() { - DOMDocumentFactory fact = (DOMDocumentFactory) singleton.instance(); - return fact; + return singleton.instance(); } // Factory methods @@ -83,7 +71,7 @@ public class DOMDocumentFactory extends DocumentFactory implements } public DocumentType createDocType(String name, String publicId, - String systemId) { + String systemId) { return new DOMDocumentType(name, publicId, systemId); } @@ -124,12 +112,12 @@ public class DOMDocumentFactory extends DocumentFactory implements } public ProcessingInstruction createProcessingInstruction(String target, - String data) { + String data) { return new DOMProcessingInstruction(target, data); } public ProcessingInstruction createProcessingInstruction(String target, - Map data) { + Map data) { return new DOMProcessingInstruction(target, data); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentType.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentType.java index 6352752b4..fdc1f3b2f 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentType.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMDocumentType.java @@ -8,12 +8,7 @@ package org.dom4j.dom; import org.dom4j.tree.DefaultDocumentType; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; /** *

@@ -22,7 +17,7 @@ import org.w3c.dom.UserDataHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ */ public class DOMDocumentType extends DefaultDocumentType implements org.w3c.dom.DocumentType { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMElement.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMElement.java index 6a22bfbb4..139dad56b 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMElement.java @@ -7,19 +7,12 @@ package org.dom4j.dom; -import org.dom4j.Attribute; -import org.dom4j.DocumentFactory; -import org.dom4j.Namespace; -import org.dom4j.QName; +import org.dom4j.*; import org.dom4j.tree.DefaultElement; -import org.w3c.dom.Attr; -import org.w3c.dom.DOMException; +import org.w3c.dom.*; import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Element; import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.TypeInfo; -import org.w3c.dom.UserDataHandler; import java.util.ArrayList; import java.util.List; @@ -31,7 +24,7 @@ import java.util.List; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.23 $ */ public class DOMElement extends DefaultElement implements org.w3c.dom.Element { /** The DocumentFactory instance used by default */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMEntityReference.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMEntityReference.java index 1e1dafb5f..f3c62a6db 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMEntityReference.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMEntityReference.java @@ -9,12 +9,7 @@ package org.dom4j.dom; import org.dom4j.Element; import org.dom4j.tree.DefaultEntity; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; /** *

@@ -23,7 +18,7 @@ import org.w3c.dom.UserDataHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public class DOMEntityReference extends DefaultEntity implements org.w3c.dom.EntityReference { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNamespace.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNamespace.java index c02d690e2..e273d8b91 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNamespace.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNamespace.java @@ -9,12 +9,7 @@ package org.dom4j.dom; import org.dom4j.Element; import org.dom4j.tree.DefaultNamespace; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; /** *

@@ -23,7 +18,7 @@ import org.w3c.dom.UserDataHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class DOMNamespace extends DefaultNamespace implements org.w3c.dom.Node { public DOMNamespace(String prefix, String uri) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNodeHelper.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNodeHelper.java index a591710f3..cfc749095 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNodeHelper.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMNodeHelper.java @@ -7,12 +7,7 @@ package org.dom4j.dom; -import org.dom4j.Branch; -import org.dom4j.CharacterData; -import org.dom4j.Document; -import org.dom4j.DocumentType; -import org.dom4j.Element; -import org.dom4j.Node; +import org.dom4j.*; import org.w3c.dom.DOMException; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NodeList; @@ -26,7 +21,7 @@ import java.util.List; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.20 $ */ public class DOMNodeHelper { public static final NodeList EMPTY_NODE_LIST = new EmptyNodeList(); @@ -127,14 +122,15 @@ public class DOMNodeHelper { org.w3c.dom.Node newChild, org.w3c.dom.Node refChild) throws DOMException { if (node instanceof Branch) { + assert newChild instanceof Node; Branch branch = (Branch) node; - List list = branch.content(); + List list = branch.content(); int index = list.indexOf(refChild); if (index < 0) { branch.add((Node) newChild); } else { - list.add(index, newChild); + list.add(index, (Node) newChild); } return newChild; @@ -149,7 +145,8 @@ public class DOMNodeHelper { throws DOMException { if (node instanceof Branch) { Branch branch = (Branch) node; - List list = branch.content(); + List list = branch.content(); + assert newChild instanceof Node; int index = list.indexOf(oldChild); if (index < 0) { @@ -158,7 +155,7 @@ public class DOMNodeHelper { + node); } - list.set(index, newChild); + list.set(index, (Node) newChild); return oldChild; } else { @@ -271,7 +268,7 @@ public class DOMNodeHelper { String text = charData.getText(); if (text == null) { - charData.setText(text); + charData.setText(arg); } else { charData.setText(text + arg); } @@ -295,7 +292,7 @@ public class DOMNodeHelper { throw new DOMException(DOMException.INDEX_SIZE_ERR, "No text at offset: " + offset); } else { - StringBuffer buffer = new StringBuffer(text); + StringBuilder buffer = new StringBuilder(text); buffer.insert(offset, arg); data.setText(buffer.toString()); } @@ -323,7 +320,7 @@ public class DOMNodeHelper { throw new DOMException(DOMException.INDEX_SIZE_ERR, "No text at offset: " + offset); } else { - StringBuffer buffer = new StringBuffer(text); + StringBuilder buffer = new StringBuilder(text); buffer.delete(offset, offset + count); charData.setText(buffer.toString()); } @@ -351,7 +348,7 @@ public class DOMNodeHelper { throw new DOMException(DOMException.INDEX_SIZE_ERR, "No text at offset: " + offset); } else { - StringBuffer buffer = new StringBuffer(text); + StringBuilder buffer = new StringBuilder(text); buffer.replace(offset, offset + count, arg); charData.setText(buffer.toString()); } @@ -361,7 +358,7 @@ public class DOMNodeHelper { // Branch API // ------------------------------------------------------------------------- - public static void appendElementsByTagName(List list, Branch parent, + public static void appendElementsByTagName(List list, Branch parent, String name) { final boolean isStar = "*".equals(name); @@ -380,7 +377,7 @@ public class DOMNodeHelper { } } - public static void appendElementsByTagNameNS(List list, Branch parent, + public static void appendElementsByTagNameNS(List list, Branch parent, String namespace, String localName) { final boolean isStarNS = "*".equals(namespace); final boolean isStar = "*".equals(localName); @@ -409,7 +406,7 @@ public class DOMNodeHelper { // Helper methods // ------------------------------------------------------------------------- - public static NodeList createNodeList(final List list) { + public static NodeList createNodeList(final List list) { return new NodeList() { public org.w3c.dom.Node item(int index) { if (index >= getLength()) { @@ -420,7 +417,7 @@ public class DOMNodeHelper { */ return null; } else { - return DOMNodeHelper.asDOMNode((Node) list.get(index)); + return DOMNodeHelper.asDOMNode(list.get(index)); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMProcessingInstruction.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMProcessingInstruction.java index f4344ed45..87e7b1df5 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMProcessingInstruction.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMProcessingInstruction.java @@ -9,12 +9,7 @@ package org.dom4j.dom; import org.dom4j.Element; import org.dom4j.tree.DefaultProcessingInstruction; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; import java.util.Map; @@ -25,11 +20,11 @@ import java.util.Map; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public class DOMProcessingInstruction extends DefaultProcessingInstruction implements org.w3c.dom.ProcessingInstruction { - public DOMProcessingInstruction(String target, Map values) { + public DOMProcessingInstruction(String target, Map values) { super(target, values); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMText.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMText.java index dad882629..525a72cfc 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMText.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/DOMText.java @@ -10,12 +10,7 @@ package org.dom4j.dom; import org.dom4j.Element; import org.dom4j.Text; import org.dom4j.tree.DefaultText; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.UserDataHandler; +import org.w3c.dom.*; /** *

@@ -23,7 +18,7 @@ import org.w3c.dom.UserDataHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public class DOMText extends DefaultText implements org.w3c.dom.Text { public DOMText(String text) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/dom/package-info.java new file mode 100644 index 000000000..cb74834f1 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/dom/package-info.java @@ -0,0 +1,4 @@ +/** + * An implementation of the dom4j API which also supports the W3C object model. + */ +package org.dom4j.dom; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dom/package.html b/fine-org-dom4j/src/main/java/org/dom4j/dom/package.html deleted file mode 100644 index b86c30f3b..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/dom/package.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -

An implementation of the dom4j API which also supports the - W3C object model.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dtd/AttributeDecl.java b/fine-org-dom4j/src/main/java/org/dom4j/dtd/AttributeDecl.java index 77f99eaaf..e20e7202c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dtd/AttributeDecl.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dtd/AttributeDecl.java @@ -13,9 +13,9 @@ package org.dom4j.dtd; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ -public class AttributeDecl { +public class AttributeDecl implements Decl { /** Holds value of property elementName. */ private String elementName; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dtd/Decl.java b/fine-org-dom4j/src/main/java/org/dom4j/dtd/Decl.java new file mode 100644 index 000000000..f05d32df5 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/dtd/Decl.java @@ -0,0 +1,7 @@ +package org.dom4j.dtd; + +/** + * Created by filip on 5.7.15. + */ +public interface Decl { +} diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dtd/ElementDecl.java b/fine-org-dom4j/src/main/java/org/dom4j/dtd/ElementDecl.java index 9447e1873..c4abb3f63 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dtd/ElementDecl.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dtd/ElementDecl.java @@ -13,9 +13,9 @@ package org.dom4j.dtd; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.6 $ */ -public class ElementDecl { +public class ElementDecl implements Decl { /** Holds value of property name. */ private String name; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dtd/ExternalEntityDecl.java b/fine-org-dom4j/src/main/java/org/dom4j/dtd/ExternalEntityDecl.java index 645cbb642..c02da0381 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dtd/ExternalEntityDecl.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dtd/ExternalEntityDecl.java @@ -14,9 +14,9 @@ package org.dom4j.dtd; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ -public class ExternalEntityDecl { +public class ExternalEntityDecl implements Decl { /** Holds value of property name. */ private String name; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dtd/InternalEntityDecl.java b/fine-org-dom4j/src/main/java/org/dom4j/dtd/InternalEntityDecl.java index d53fc96de..cd6d46ebc 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/dtd/InternalEntityDecl.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/dtd/InternalEntityDecl.java @@ -14,9 +14,9 @@ package org.dom4j.dtd; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ -public class InternalEntityDecl { +public class InternalEntityDecl implements Decl { /** Holds value of property name. */ private String name; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dtd/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/dtd/package-info.java new file mode 100644 index 000000000..27b3cd690 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/dtd/package-info.java @@ -0,0 +1,4 @@ +/** + * Classes to represent the DTD declarations. They are used inside the {@link org.dom4j.DocumentType} interface. + */ +package org.dom4j.dtd; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/dtd/package.html b/fine-org-dom4j/src/main/java/org/dom4j/dtd/package.html deleted file mode 100644 index af655947a..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/dtd/package.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - -

Classes to represent the DTD declarations. They are used inside the {@link org.dom4j.DocumentType} interface.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DOMDocumentResult.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMDocumentResult.java new file mode 100644 index 000000000..5f579bbe3 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMDocumentResult.java @@ -0,0 +1,102 @@ +/* + * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. + * + * This software is open source. + * See the bottom of this file for the licence. + */ + +package org.dom4j.io; + +import javax.xml.transform.sax.SAXResult; + +import org.w3c.dom.Document; + +import org.xml.sax.ContentHandler; +import org.xml.sax.ext.LexicalHandler; + +/** + *

+ * DOMDocumentResult implements a JAXP {@link SAXResult} for a + * {@link org.w3c.dom.Document}. + *

+ * + * @author James Strachan + * @author Todd Wolff + * @version $Revision: 1.1 $ + */ +public class DOMDocumentResult extends SAXResult { + private DOMSAXContentHandler contentHandler; + + public DOMDocumentResult() { + this(new DOMSAXContentHandler()); + } + + public DOMDocumentResult(DOMSAXContentHandler contentHandler) { + this.contentHandler = contentHandler; + super.setHandler(this.contentHandler); + super.setLexicalHandler(this.contentHandler); + } + + /** + * Retrieves w3c dom object generated via transformation + * + * @return the Document created by the transformation + */ + public Document getDocument() { + return contentHandler.getDocument(); + } + + // Overloaded methods + // ------------------------------------------------------------------------- + public void setHandler(ContentHandler handler) { + if (handler instanceof DOMSAXContentHandler) { + this.contentHandler = (DOMSAXContentHandler) handler; + super.setHandler(this.contentHandler); + } + } + + public void setLexicalHandler(LexicalHandler handler) { + if (handler instanceof DOMSAXContentHandler) { + this.contentHandler = (DOMSAXContentHandler) handler; + super.setLexicalHandler(this.contentHandler); + } + } + +} + +/* + * Redistribution and use of this software and associated documentation + * ("Software"), with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain copyright statements and + * notices. Redistributions must also contain a copy of this document. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name "DOM4J" must not be used to endorse or promote products derived + * from this Software without prior written permission of MetaStuff, Ltd. For + * written permission, please contact dom4j-info@metastuff.com. + * + * 4. Products derived from this Software may not be called "DOM4J" nor may + * "DOM4J" appear in their names without prior written permission of MetaStuff, + * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. + * + * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org + * + * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. + */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DOMReader.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMReader.java index 7debed853..0fc85a951 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/DOMReader.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMReader.java @@ -10,12 +10,8 @@ package org.dom4j.io; import java.util.ArrayList; import java.util.List; -import org.dom4j.Branch; -import org.dom4j.Document; -import org.dom4j.DocumentFactory; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; +import org.dom4j.*; +import org.dom4j.dom.DOMAttribute; import org.dom4j.tree.NamespaceStack; /** @@ -25,7 +21,7 @@ import org.dom4j.tree.NamespaceStack; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.17 $ */ public class DOMReader { /** DocumentFactory used to create new document objects */ @@ -201,11 +197,10 @@ public class DOMReader { if (attributeList != null) { int size = attributeList.getLength(); - List attributes = new ArrayList(size); + List attributes = new ArrayList(size); for (int i = 0; i < size; i++) { org.w3c.dom.Node attribute = attributeList.item(i); - // Define all namespaces first then process attributes later String name = attribute.getNodeName(); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DOMSAXContentHandler.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMSAXContentHandler.java new file mode 100644 index 000000000..821590c9b --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMSAXContentHandler.java @@ -0,0 +1,548 @@ +/* + * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. + * + * This software is open source. + * See the bottom of this file for the licence. + */ + +package org.dom4j.io; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.dom4j.Branch; +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.Namespace; +import org.dom4j.QName; +import org.dom4j.dom.DOMAttribute; +import org.dom4j.dom.DOMCDATA; +import org.dom4j.dom.DOMComment; +import org.dom4j.dom.DOMDocumentFactory; +import org.dom4j.dom.DOMElement; +import org.dom4j.dom.DOMText; +import org.dom4j.tree.NamespaceStack; +import org.w3c.dom.ProcessingInstruction; +import org.xml.sax.Attributes; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.ext.Locator2; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

+ * SAXContentHandler builds W3C DOM object via SAX events. + * + * @author James Strachan + * @author Todd Wolff + * + *

+ */ +public class DOMSAXContentHandler extends DefaultHandler implements LexicalHandler { + + /** The factory used to create new Document instances */ + private DOMDocumentFactory documentFactory; + + /** The document that is being built */ + private Document document; + + /** stack of Element objects */ + private ElementStack elementStack; + + /** stack of Namespace and QName objects */ + private NamespaceStack namespaceStack; + + /** the Locator */ + private Locator locator; + + /** Flag used to indicate that we are inside a CDATA section */ + private boolean insideCDATASection; + + /** + * buffer to hold contents of cdata section across multiple characters + * events + */ + private StringBuffer cdataText; + + /** The number of namespaces that are declared in the current scope */ + private int declaredNamespaceIndex; + + private InputSource inputSource; + + /** The current element we are on */ + private Element currentElement; + + /** The entity resolver */ + private EntityResolver entityResolver; + + /** Whether adjacent text nodes should be merged */ + private boolean mergeAdjacentText = false; + + /** Have we added text to the buffer */ + private boolean textInTextBuffer = false; + + /** Should we ignore comments */ + private boolean ignoreComments = false; + + /** Buffer used to concatenate text together */ + private StringBuffer textBuffer; + + /** Holds value of property stripWhitespaceText. */ + private boolean stripWhitespaceText = false; + + public DOMSAXContentHandler() { + this((DOMDocumentFactory)DOMDocumentFactory.getInstance()); + } + + public DOMSAXContentHandler(DOMDocumentFactory documentFactory) { + this.documentFactory = documentFactory; + this.elementStack = createElementStack(); + this.namespaceStack = new NamespaceStack(documentFactory); + } + + /** + * Retrieves w3c document object built via generated sax events. + * + * @return the document that has been or is being built + */ + public org.w3c.dom.Document getDocument() { + if (document == null) { + document = createDocument(); + } + + return (org.w3c.dom.Document)document; + } + + // ContentHandler interface + // ------------------------------------------------------------------------- + public void setDocumentLocator(Locator documentLocator) { + this.locator = documentLocator; + } + + public void processingInstruction(String target, String data) + throws SAXException { + if (mergeAdjacentText && textInTextBuffer) { + completeCurrentTextNode(); + } + ProcessingInstruction pi = (ProcessingInstruction)documentFactory.createProcessingInstruction(target, data); + if (currentElement != null) { + ((org.w3c.dom.Element)currentElement).appendChild(pi); + } else { + getDocument().appendChild(pi); + } + } + + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + namespaceStack.push(prefix, uri); + } + + public void endPrefixMapping(String prefix) throws SAXException { + namespaceStack.pop(prefix); + declaredNamespaceIndex = namespaceStack.size(); + } + + public void startDocument() throws SAXException { + document = null; + currentElement = null; + + elementStack.clear(); + + namespaceStack.clear(); + declaredNamespaceIndex = 0; + + if (mergeAdjacentText && (textBuffer == null)) { + textBuffer = new StringBuffer(); + } + + textInTextBuffer = false; + } + + public void endDocument() throws SAXException { + namespaceStack.clear(); + elementStack.clear(); + currentElement = null; + textBuffer = null; + } + + public void startElement(String namespaceURI, String localName, + String qualifiedName, Attributes attributes) throws SAXException { + if (mergeAdjacentText && textInTextBuffer) { + completeCurrentTextNode(); + } + + QName qName = namespaceStack.getQName(namespaceURI, localName, + qualifiedName); + + Branch branch = currentElement; + + if (branch == null) { + branch = (org.dom4j.Document)getDocument(); + } + + Element element = new DOMElement(qName); + branch.add(element); + + // add all declared namespaces + addDeclaredNamespaces(element); + + // now lets add all attribute values + addAttributes(element, attributes); + + elementStack.pushElement(element); + currentElement = element; + + } + + public void endElement(String namespaceURI, String localName, String qName) + throws SAXException { + if (mergeAdjacentText && textInTextBuffer) { + completeCurrentTextNode(); + } + + elementStack.popElement(); + currentElement = elementStack.peekElement(); + } + + public void characters(char[] ch, int start, int end) throws SAXException { + if (end == 0) { + return; + } + + if (currentElement != null) { + if (insideCDATASection) { + if (mergeAdjacentText && textInTextBuffer) { + completeCurrentTextNode(); + } + cdataText.append(new String(ch, start, end)); + } else { + if (mergeAdjacentText) { + textBuffer.append(ch, start, end); + textInTextBuffer = true; + } else { + DOMText text = new DOMText(new String(ch, start, end)); + ((DOMElement)currentElement).add(text); + } + } + } + } + + // ErrorHandler interface + // ------------------------------------------------------------------------- + + /** + * This method is called when a warning occurs during the parsing of the + * document. This method does nothing. + * + * @param exception + * DOCUMENT ME! + * + * @throws SAXException + * DOCUMENT ME! + */ + public void warning(SAXParseException exception) throws SAXException { + // ignore warnings by default + } + + /** + * This method is called when an error is detected during parsing such as a + * validation error. This method rethrows the exception + * + * @param exception + * DOCUMENT ME! + * + * @throws SAXException + * DOCUMENT ME! + */ + public void error(SAXParseException exception) throws SAXException { + throw exception; + } + + /** + * This method is called when a fatal error occurs during parsing. This + * method rethrows the exception + * + * @param exception + * DOCUMENT ME! + * + * @throws SAXException + * DOCUMENT ME! + */ + public void fatalError(SAXParseException exception) throws SAXException { + throw exception; + } + + // LexicalHandler interface + // ------------------------------------------------------------------------- + public void startDTD(String name, String publicId, String systemId) + throws SAXException { + // not supported + } + + public void endDTD() throws SAXException { + // not supported + } + + public void startEntity(String name) throws SAXException { + // not supported + } + + public void endEntity(String name) throws SAXException { + // not supported + } + + public void startCDATA() throws SAXException { + insideCDATASection = true; + cdataText = new StringBuffer(); + } + + public void endCDATA() throws SAXException { + insideCDATASection = false; + DOMCDATA cdata = new DOMCDATA(cdataText.toString()); + ((DOMElement)currentElement).add(cdata); + } + + public void comment(char[] ch, int start, int end) throws SAXException { + if (!ignoreComments) { + if (mergeAdjacentText && textInTextBuffer) { + completeCurrentTextNode(); + } + + String text = new String(ch, start, end); + + if (text.length() > 0) { + DOMComment domComment = new DOMComment(text); + if (currentElement != null) { + ((DOMElement)currentElement).add(domComment); + } else { + getDocument().appendChild(domComment); + } + } + } + } + + // Properties + // ------------------------------------------------------------------------- + public ElementStack getElementStack() { + return elementStack; + } + + public void setElementStack(ElementStack elementStack) { + this.elementStack = elementStack; + } + + public EntityResolver getEntityResolver() { + return entityResolver; + } + + public void setEntityResolver(EntityResolver entityResolver) { + this.entityResolver = entityResolver; + } + + public InputSource getInputSource() { + return inputSource; + } + + public void setInputSource(InputSource inputSource) { + this.inputSource = inputSource; + } + + /** + * Returns whether adjacent text nodes should be merged together. + * + * @return Value of property mergeAdjacentText. + */ + public boolean isMergeAdjacentText() { + return mergeAdjacentText; + } + + /** + * Sets whether or not adjacent text nodes should be merged together when + * parsing. + * + * @param mergeAdjacentText + * New value of property mergeAdjacentText. + */ + public void setMergeAdjacentText(boolean mergeAdjacentText) { + this.mergeAdjacentText = mergeAdjacentText; + } + + /** + * Sets whether whitespace between element start and end tags should be + * ignored + * + * @return Value of property stripWhitespaceText. + */ + public boolean isStripWhitespaceText() { + return stripWhitespaceText; + } + + /** + * Sets whether whitespace between element start and end tags should be + * ignored. + * + * @param stripWhitespaceText + * New value of property stripWhitespaceText. + */ + public void setStripWhitespaceText(boolean stripWhitespaceText) { + this.stripWhitespaceText = stripWhitespaceText; + } + + /** + * Returns whether we should ignore comments or not. + * + * @return boolean + */ + public boolean isIgnoreComments() { + return ignoreComments; + } + + /** + * Sets whether we should ignore comments or not. + * + * @param ignoreComments + * whether we should ignore comments or not. + */ + public void setIgnoreComments(boolean ignoreComments) { + this.ignoreComments = ignoreComments; + } + + // Implementation methods + // ------------------------------------------------------------------------- + + protected void completeCurrentTextNode() { + if (stripWhitespaceText) { + boolean whitespace = true; + for (int i = 0, size = textBuffer.length(); i < size; i++) { + if (!Character.isWhitespace(textBuffer.charAt(i))) { + whitespace = false; + + break; + } + } + if (!whitespace) { + DOMText domText = new DOMText(textBuffer.toString()); + ((DOMElement)currentElement).add(domText); + } + } else { + DOMText domText = new DOMText(textBuffer.toString()); + ((DOMElement)currentElement).add(domText); + } + + textBuffer.setLength(0); + textInTextBuffer = false; + } + + protected Document createDocument() { + String encoding = getEncoding(); + Document doc = documentFactory.createDocument(encoding); + + // set the EntityResolver + doc.setEntityResolver(entityResolver); + + if (inputSource != null) { + doc.setName(inputSource.getSystemId()); + } + + return doc; + } + + private String getEncoding() { + if (locator == null) { + return null; + } + + if (locator instanceof Locator2) { + return ((Locator2) locator).getEncoding(); + } + + // couldn't determine encoding, returning null... + return null; + } + + protected void addDeclaredNamespaces(Element element) { + for (int size = namespaceStack.size(); declaredNamespaceIndex < size; + declaredNamespaceIndex++) { + Namespace namespace = namespaceStack + .getNamespace(declaredNamespaceIndex); + String attributeName = attributeNameForNamespace(namespace); + ((DOMElement)element).setAttribute(attributeName, namespace.getURI()); + } + } + + protected void addAttributes(Element element, Attributes attributes) { + int size = attributes.getLength(); + for (int i = 0; i < size; i++) { + String attributeQName = attributes.getQName(i); + if (!attributeQName.startsWith("xmlns")) { + String attributeURI = attributes.getURI(i); + String attributeLocalName = attributes.getLocalName(i); + String attributeValue = attributes.getValue(i); + QName qName = namespaceStack.getAttributeQName( + attributeURI, attributeLocalName, attributeQName); + DOMAttribute domAttribute = new DOMAttribute(qName, attributeValue); + ((DOMElement)element).setAttributeNode(domAttribute); + } + } + } + + protected ElementStack createElementStack() { + return new ElementStack(); + } + + protected String attributeNameForNamespace(Namespace namespace) { + String xmlns = "xmlns"; + String prefix = namespace.getPrefix(); + + if (prefix.length() > 0) { + return xmlns + ":" + prefix; + } + + return xmlns; + } + +} + +/* + * Redistribution and use of this software and associated documentation + * ("Software"), with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain copyright statements and + * notices. Redistributions must also contain a copy of this document. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name "DOM4J" must not be used to endorse or promote products derived + * from this Software without prior written permission of MetaStuff, Ltd. For + * written permission, please contact dom4j-info@metastuff.com. + * + * 4. Products derived from this Software may not be called "DOM4J" nor may + * "DOM4J" appear in their names without prior written permission of MetaStuff, + * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. + * + * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org + * + * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. + */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DOMWriter.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMWriter.java index aa911be0f..a074dbe51 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/DOMWriter.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DOMWriter.java @@ -9,28 +9,18 @@ package org.dom4j.io; import java.util.List; -import org.dom4j.Attribute; -import org.dom4j.CDATA; -import org.dom4j.Comment; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.Entity; -import org.dom4j.Namespace; -import org.dom4j.ProcessingInstruction; -import org.dom4j.Text; +import org.dom4j.*; +import org.dom4j.dtd.Decl; import org.dom4j.tree.NamespaceStack; import org.w3c.dom.DOMImplementation; /** - *

* DOMWriter takes a DOM4J tree and outputs it as a W3C DOM * object - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.17 $ */ public class DOMWriter { private static boolean loggedWarning = false; @@ -46,7 +36,7 @@ public class DOMWriter { }; // the Class used to create new DOM Document instances - private Class domDocumentClass; + private Class domDocumentClass; /** stack of Namespace objects */ private NamespaceStack namespaceStack = new NamespaceStack(); @@ -54,20 +44,19 @@ public class DOMWriter { public DOMWriter() { } - public DOMWriter(Class domDocumentClass) { + public DOMWriter(Class domDocumentClass) { this.domDocumentClass = domDocumentClass; } - public Class getDomDocumentClass() throws DocumentException { - Class result = domDocumentClass; + public Class getDomDocumentClass() throws DocumentException { + Class result = domDocumentClass; if (result == null) { // lets try and find one in the classpath int size = DEFAULT_DOM_DOCUMENT_CLASSES.length; - for (int i = 0; i < size; i++) { + for (String name : DEFAULT_DOM_DOCUMENT_CLASSES) { try { - String name = DEFAULT_DOM_DOCUMENT_CLASSES[i]; result = Class.forName(name, true, DOMWriter.class .getClassLoader()); @@ -89,10 +78,10 @@ public class DOMWriter { * the writer when creating DOM documents. * * @param domDocumentClass - * is the Class implementing the {@linkorg.w3c.dom.Document} + * is the Class implementing the {@link org.w3c.dom.Document} * interface */ - public void setDomDocumentClass(Class domDocumentClass) { + public void setDomDocumentClass(Class domDocumentClass) { this.domDocumentClass = domDocumentClass; } @@ -148,28 +137,22 @@ public class DOMWriter { } protected void appendDOMTree(org.w3c.dom.Document domDocument, - org.w3c.dom.Node domCurrent, List content) { - int size = content.size(); - - for (int i = 0; i < size; i++) { - Object object = content.get(i); - - if (object instanceof Element) { - appendDOMTree(domDocument, domCurrent, (Element) object); - } else if (object instanceof String) { - appendDOMTree(domDocument, domCurrent, (String) object); - } else if (object instanceof Text) { - Text text = (Text) object; + org.w3c.dom.Node domCurrent, List content) { + for (Node node : content) { + if (node instanceof Element) { + appendDOMTree(domDocument, domCurrent, (Element) node); + } else if (node instanceof Text) { + Text text = (Text) node; appendDOMTree(domDocument, domCurrent, text.getText()); - } else if (object instanceof CDATA) { - appendDOMTree(domDocument, domCurrent, (CDATA) object); - } else if (object instanceof Comment) { - appendDOMTree(domDocument, domCurrent, (Comment) object); - } else if (object instanceof Entity) { - appendDOMTree(domDocument, domCurrent, (Entity) object); - } else if (object instanceof ProcessingInstruction) { + } else if (node instanceof CDATA) { + appendDOMTree(domDocument, domCurrent, (CDATA) node); + } else if (node instanceof Comment) { + appendDOMTree(domDocument, domCurrent, (Comment) node); + } else if (node instanceof Entity) { + appendDOMTree(domDocument, domCurrent, (Entity) node); + } else if (node instanceof ProcessingInstruction) { appendDOMTree(domDocument, domCurrent, - (ProcessingInstruction) object); + (ProcessingInstruction) node); } } } @@ -192,7 +175,7 @@ public class DOMWriter { } // add the additional declared namespaces - List declaredNamespaces = element.declaredNamespaces(); + List declaredNamespaces = element.declaredNamespaces(); for (int i = 0, size = declaredNamespaces.size(); i < size; i++) { Namespace namespace = (Namespace) declaredNamespaces.get(i); @@ -204,8 +187,7 @@ public class DOMWriter { } // add the attributes - for (int i = 0, size = element.attributeCount(); i < size; i++) { - Attribute attribute = (Attribute) element.attribute(i); + for (Attribute attribute : element.attributes()) { String attUri = attribute.getNamespaceURI(); String attName = attribute.getQualifiedName(); String value = attribute.getValue(); @@ -294,7 +276,7 @@ public class DOMWriter { result = createDomDocumentViaJAXP(); if (result == null) { - Class theClass = getDomDocumentClass(); + Class theClass = getDomDocumentClass(); try { result = (org.w3c.dom.Document) theClass.newInstance(); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DispatchHandler.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DispatchHandler.java index b712b5b3e..a2ec88acb 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/DispatchHandler.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DispatchHandler.java @@ -27,7 +27,7 @@ import org.dom4j.ElementPath; *

* * @author Dave White - * @version $Revision$ + * @version $Revision: 1.11 $ */ class DispatchHandler implements ElementHandler { /** Whether the parser is at the root element or not */ @@ -37,16 +37,16 @@ class DispatchHandler implements ElementHandler { private String path; /** maintains a stack of previously encountered paths */ - private ArrayList pathStack; + private ArrayList pathStack; /** maintains a stack of previously encountered handlers */ - private ArrayList handlerStack; + private ArrayList handlerStack; /** * HashMap maintains the mapping between element paths and * handlers */ - private HashMap handlers; + private HashMap handlers; /** * ElementHandler to use by default for element paths with no @@ -57,9 +57,9 @@ class DispatchHandler implements ElementHandler { public DispatchHandler() { atRoot = true; path = "/"; - pathStack = new ArrayList(); - handlerStack = new ArrayList(); - handlers = new HashMap(); + pathStack = new ArrayList(); + handlerStack = new ArrayList(); + handlers = new HashMap(); } /** @@ -86,7 +86,7 @@ class DispatchHandler implements ElementHandler { * @return DOCUMENT ME! */ public ElementHandler removeHandler(String handlerPath) { - return (ElementHandler) handlers.remove(handlerPath); + return handlers.remove(handlerPath); } /** @@ -111,7 +111,7 @@ class DispatchHandler implements ElementHandler { * @return the registered handler */ public ElementHandler getHandler(String handlerPath) { - return (ElementHandler) handlers.get(handlerPath); + return handlers.get(handlerPath); } /** @@ -177,7 +177,7 @@ class DispatchHandler implements ElementHandler { if ((handlers != null) && (handlers.containsKey(path))) { // The current node has a handler associated with it. // Find the handler and save it on the handler stack. - ElementHandler handler = (ElementHandler) handlers.get(path); + ElementHandler handler = handlers.get(path); handlerStack.add(handler); // Call the handlers onStart method. @@ -195,7 +195,7 @@ class DispatchHandler implements ElementHandler { if ((handlers != null) && (handlers.containsKey(path))) { // This node has a handler associated with it. // Find the handler and pop it from the handler stack. - ElementHandler handler = (ElementHandler) handlers.get(path); + ElementHandler handler = handlers.get(path); handlerStack.remove(handlerStack.size() - 1); // Call the handlers onEnd method @@ -209,7 +209,7 @@ class DispatchHandler implements ElementHandler { } // Set path back to its parent - path = (String) pathStack.remove(pathStack.size() - 1); + path = pathStack.remove(pathStack.size() - 1); if (pathStack.size() == 0) { atRoot = true; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentInputSource.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentInputSource.java index a24bbb92c..35c8ece51 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentInputSource.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentInputSource.java @@ -23,7 +23,7 @@ import org.xml.sax.InputSource; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ class DocumentInputSource extends InputSource { /** The document source */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentResult.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentResult.java index efca88575..3bca881ba 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentResult.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentResult.java @@ -21,7 +21,7 @@ import org.xml.sax.ext.LexicalHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ public class DocumentResult extends SAXResult { private SAXContentHandler contentHandler; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentSource.java b/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentSource.java index 2745d6cfa..1cc206930 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentSource.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/DocumentSource.java @@ -17,13 +17,11 @@ import org.xml.sax.XMLFilter; import org.xml.sax.XMLReader; /** - *

* DocumentSource implements a JAXP {@link SAXSource}for a - * {@linkDocument}. - *

- * + * {@link Document}. + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class DocumentSource extends SAXSource { /** @@ -93,7 +91,7 @@ public class DocumentSource extends SAXSource { } /** - * This method is not supported as this source is always a {@linkDocument} + * This method is not supported as this source is always a {@link Document} * instance. * * @param inputSource diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/ElementStack.java b/fine-org-dom4j/src/main/java/org/dom4j/io/ElementStack.java index 6466ac03d..1284dd2aa 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/ElementStack.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/ElementStack.java @@ -20,7 +20,7 @@ import org.dom4j.ElementPath; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.14 $ */ class ElementStack implements ElementPath { /** stack of Element objects */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/HTMLWriter.java b/fine-org-dom4j/src/main/java/org/dom4j/io/HTMLWriter.java index 3a0b2316f..719d822e9 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/HTMLWriter.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/HTMLWriter.java @@ -26,25 +26,21 @@ import org.dom4j.Node; import org.xml.sax.SAXException; /** - *

* HTMLWriter takes a DOM4J tree and formats it to a stream as * HTML. This formatter is similar to XMLWriter but it outputs the text of CDATA * and Entity sections rather than the serialised format as in XML, it has an * XHTML mode, it retains whitespace in certain elements such as <PRE>, * and it supports certain elements which have no corresponding close tag such * as for <BR> and <P>. - *

- * - *

+ * * The OutputFormat passed in to the constructor is checked for isXHTML() and * isExpandEmptyElements(). See {@link OutputFormat OutputFormat}for details. * Here are the rules for this class based on an OutputFormat, "format", - * passed in to the constructor:

+ * passed in to the constructor: * *

    *
  • If an element is in {@link #getOmitElementCloseSet() * getOmitElementCloseSet}, then it is treated specially: - * *
      *
    • It never expands, since some browsers treat this as two separate * Horizontal Rules: <HR></HR>
    • @@ -54,7 +50,6 @@ import org.xml.sax.SAXException; * "/", but that's better than when it refuses to recognize this: <hr/> * which it thinks is an element named "HR/". *
    - * *
  • *
  • If {@link org.dom4j.io.OutputFormat#isXHTML() format.isXHTML()}, all * elements must have either a close element, or be a closed single tag.
  • @@ -62,41 +57,21 @@ import org.xml.sax.SAXException; * format.isExpandEmptyElements()}() is true, all elements are expanded except * as above. *
- * * Examples - *

- * - *

- *

- * - *

* If isXHTML == true, CDATA sections look like this: - * - *

- * 
+ * 
  * <myelement><![CDATA[My data]]></myelement> 
- * 
- * 
- * + *
* Otherwise, they look like this: - * - *
- * 
+ * 
  * <myelement>My data</myelement> 
- * 
- * 
- * - *

- * - *

- * Basically, {@link OutputFormat.isXHTML() OutputFormat.isXHTML()} == + *

+ + * Basically, {@link OutputFormat#isXHTML()} == * true will produce valid XML, while {@link - * org.dom4j.io.OutputFormat#isExpandEmptyElements() - * format.isExpandEmptyElements()} determines whether empty elements are + * OutputFormat#isExpandEmptyElements()} determines whether empty elements are * expanded if isXHTML is true, excepting the special HTML single tags. - *

- * - *

+ * * Also, HTMLWriter handles tags whose contents should be preformatted, that is, * whitespace-preserved. By default, this set includes the tags <PRE>, * <SCRIPT>, <STYLE>, and <TEXTAREA>, case insensitively. It @@ -107,29 +82,15 @@ import org.xml.sax.SAXException; * However, the parser you use may store comments with linefeed-only text nodes * (\n) even if your platform uses another line.separator character, and * HTMLWriter outputs Comment nodes exactly as the DOM is set up by the parser. - * See examples and discussion here: {@link#setPreformattedTags(java.util.Set) - * setPreformattedTags} - *

- * - *

+ * See examples and discussion here: {@link #setPreformattedTags(java.util.Set)} + * * Examples - *

- *
- *

* Pretty Printing - *

- * - *

* This example shows how to pretty print a string containing a valid HTML * document to a string. You can also just call the static methods of this - * class:
- * {@link #prettyPrintHTML(String) prettyPrintHTML(String)}or
- * {@link #prettyPrintHTML(String,boolean,boolean,boolean,boolean) - * prettyPrintHTML(String,boolean,boolean,boolean,boolean)} or,
- * {@link #prettyPrintXHTML(String) prettyPrintXHTML(String)}for XHTML (note - * the X) - *

- * + * class: {@link #prettyPrintHTML(String)}or {@link #prettyPrintHTML(String,boolean,boolean,boolean,boolean)} + * or {@link #prettyPrintXHTML(String)} for XHTML (note the X) + * *
  * String testPrettyPrint(String html) {
  *     StringWriter sw = new StringWriter();
@@ -147,13 +108,11 @@ import org.xml.sax.SAXException;
  * }
  * 
* - *

* This example shows how to create a "squeezed" document, but one that will * work in browsers even if the browser line length is limited. No newlines are * included, no extra whitespace at all, except where it it required by * {@link #setPreformattedTags(java.util.Set) setPreformattedTags}. - *

- * + * *
  * String testCrunch(String html) {
  *     StringWriter sw = new StringWriter();
@@ -171,22 +130,20 @@ import org.xml.sax.SAXException;
  *     return sw.toString();
  * }
  * 
- * - *
- * + * * @author James Strachan * @author Laramie Crocker - * @version $Revision$ + * @version $Revision: 1.21 $ */ public class HTMLWriter extends XMLWriter { private static String lineSeparator = System.getProperty("line.separator"); - protected static final HashSet DEFAULT_PREFORMATTED_TAGS; + protected static final HashSet DEFAULT_PREFORMATTED_TAGS; static { // If you change this list, update the javadoc examples, above in the // class javadoc, in writeElement, and in setPreformattedTags(). - DEFAULT_PREFORMATTED_TAGS = new HashSet(); + DEFAULT_PREFORMATTED_TAGS = new HashSet(); DEFAULT_PREFORMATTED_TAGS.add("PRE"); DEFAULT_PREFORMATTED_TAGS.add("SCRIPT"); DEFAULT_PREFORMATTED_TAGS.add("STYLE"); @@ -201,7 +158,7 @@ public class HTMLWriter extends XMLWriter { DEFAULT_HTML_FORMAT.setSuppressDeclaration(true); } - private Stack formatStack = new Stack(); + private Stack formatStack = new Stack(); private String lastText = ""; @@ -210,13 +167,13 @@ public class HTMLWriter extends XMLWriter { // legal values are 0+, but -1 signifies lazy initialization. private int newLineAfterNTags = -1; - private HashSet preformattedTags = DEFAULT_PREFORMATTED_TAGS; + private HashSet preformattedTags = DEFAULT_PREFORMATTED_TAGS; /** * Used to store the qualified element names which should have no close * element tag */ - private HashSet omitElementCloseSet; + private HashSet omitElementCloseSet; public HTMLWriter(Writer writer) { super(writer, DEFAULT_HTML_FORMAT); @@ -349,9 +306,9 @@ public class HTMLWriter extends XMLWriter { qualifiedName.toUpperCase()); } - private HashSet internalGetOmitElementCloseSet() { + private HashSet internalGetOmitElementCloseSet() { if (omitElementCloseSet == null) { - omitElementCloseSet = new HashSet(); + omitElementCloseSet = new HashSet(); loadOmitElementCloseSet(omitElementCloseSet); } @@ -359,7 +316,7 @@ public class HTMLWriter extends XMLWriter { } // If you change this, change the javadoc for getOmitElementCloseSet. - protected void loadOmitElementCloseSet(Set set) { + protected void loadOmitElementCloseSet(Set set) { set.add("AREA"); set.add("BASE"); set.add("BR"); @@ -382,8 +339,8 @@ public class HTMLWriter extends XMLWriter { * * @return A clone of the Set. */ - public Set getOmitElementCloseSet() { - return (Set) (internalGetOmitElementCloseSet().clone()); + public Set getOmitElementCloseSet() { + return (Set) (internalGetOmitElementCloseSet().clone()); } /** @@ -402,21 +359,17 @@ public class HTMLWriter extends XMLWriter { * @param newSet * DOCUMENT ME! */ - public void setOmitElementCloseSet(Set newSet) { + public void setOmitElementCloseSet(Set newSet) { // resets, and safely empties it out if newSet is null. - omitElementCloseSet = new HashSet(); + omitElementCloseSet = new HashSet(); if (newSet != null) { - omitElementCloseSet = new HashSet(); - - Object aTag; - Iterator iter = newSet.iterator(); + omitElementCloseSet = new HashSet(); - while (iter.hasNext()) { - aTag = iter.next(); + for (String aTag : newSet) { if (aTag != null) { - omitElementCloseSet.add(aTag.toString().toUpperCase()); + omitElementCloseSet.add(aTag.toUpperCase()); } } } @@ -424,22 +377,18 @@ public class HTMLWriter extends XMLWriter { /** * @see #setPreformattedTags(java.util.Set) setPreformattedTags + * + * @return DOCUMENT ME! */ - public Set getPreformattedTags() { - return (Set) (preformattedTags.clone()); + public Set getPreformattedTags() { + return (Set) (preformattedTags.clone()); } /** - *

* Override the default set, which includes PRE, SCRIPT, STYLE, and * TEXTAREA, case insensitively. - *

- * - *

+ * * Setting Preformatted Tags - *

- * - *

* Pass in a Set of Strings, one for each tag name that should be treated * like a PRE tag. You may pass in null or an empty Set to assign the empty * set, in which case no tags will be treated as preformatted, except that @@ -448,9 +397,7 @@ public class HTMLWriter extends XMLWriter { * preserved, including whitespace on the same line preceding the close tag. * This will generally make the close tag not line up with the start tag, * but it preserves the intention of the whitespace within the tag. - *

- * - *

+ * * The browser considers leading whitespace before the close tag to be * significant, but leading whitespace before the open tag to be * insignificant. For example, if the HTML author doesn't put the close @@ -459,13 +406,8 @@ public class HTMLWriter extends XMLWriter { * the HTML author's intent. Similarly, in a PRE, the browser treats a * flushed left close PRE tag as different from a close tag with leading * whitespace. Again, this must be left up to the HTML author. - *

- * - *

+ * * Examples - *

- *
- *

* Here is an example of how you can set the PreformattedTags list using * setPreformattedTags to include IFRAME, as well as the default set, if you * have an instance of this class named myHTMLWriter: @@ -519,29 +461,21 @@ public class HTMLWriter extends XMLWriter { * * * - * - *

- *
- * + * * @param newSet * DOCUMENT ME! */ - public void setPreformattedTags(Set newSet) { + public void setPreformattedTags(Set newSet) { // no fancy merging, just set it, assuming they did a // getExcludeTrimTags() first if they wanted to preserve the default // set. // resets, and safely empties it out if newSet is null. - preformattedTags = new HashSet(); + preformattedTags = new HashSet(); if (newSet != null) { - Object aTag; - Iterator iter = newSet.iterator(); - - while (iter.hasNext()) { - aTag = iter.next(); - + for (String aTag : newSet) { if (aTag != null) { - preformattedTags.add(aTag.toString().toUpperCase()); + preformattedTags.add(aTag.toUpperCase()); } } } @@ -687,9 +621,9 @@ public class HTMLWriter extends XMLWriter { * close tags off of the default omitElementCloseSet set. Use one of * the write methods if you want stream output. * - * @throws java.io.IOException - * @throws java.io.UnsupportedEncodingException - * @throws org.dom4j.DocumentException + * @throws java.io.IOException DOCUMENT ME! + * @throws java.io.UnsupportedEncodingException DOCUMENT ME! + * @throws org.dom4j.DocumentException DOCUMENT ME! */ public static String prettyPrintHTML(String html) throws java.io.IOException, java.io.UnsupportedEncodingException, @@ -709,9 +643,9 @@ public class HTMLWriter extends XMLWriter { * converted to XHTML empty tags: <HR/> Use one of the write * methods if you want stream output. * - * @throws java.io.IOException - * @throws java.io.UnsupportedEncodingException - * @throws org.dom4j.DocumentException + * @throws java.io.IOException DOCUMENT ME! + * @throws java.io.UnsupportedEncodingException DOCUMENT ME! + * @throws org.dom4j.DocumentException DOCUMENT ME! */ public static String prettyPrintXHTML(String html) throws java.io.IOException, java.io.UnsupportedEncodingException, @@ -739,9 +673,9 @@ public class HTMLWriter extends XMLWriter { * override allows you to specify various formatter options. Use one * of the write methods if you want stream output. * - * @throws java.io.IOException - * @throws java.io.UnsupportedEncodingException - * @throws org.dom4j.DocumentException + * @throws java.io.IOException DOCUMENT ME! + * @throws java.io.UnsupportedEncodingException DOCUMENT ME! + * @throws org.dom4j.DocumentException DOCUMENT ME! */ public static String prettyPrintHTML(String html, boolean newlines, boolean trim, boolean isXHTML, boolean expandEmpty) diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/JAXPHelper.java b/fine-org-dom4j/src/main/java/org/dom4j/io/JAXPHelper.java index 790d5dc00..e0aa8ebab 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/JAXPHelper.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/JAXPHelper.java @@ -20,7 +20,7 @@ import org.xml.sax.XMLReader; * such that dom4j can work without JAXP on the CLASSPATH * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ class JAXPHelper { protected JAXPHelper() { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/OutputFormat.java b/fine-org-dom4j/src/main/java/org/dom4j/io/OutputFormat.java index b30e1ca2e..c3acf1434 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/OutputFormat.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/OutputFormat.java @@ -8,13 +8,11 @@ package org.dom4j.io; /** - *

* OutputFormat represents the format configuration used by - * {@linkXMLWriter}and its base classes to format the XML output - *

- * + * {@link XMLWriter}and its base classes to format the XML output + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.17 $ */ public class OutputFormat implements Cloneable { /** standard value to indent by, if we are indenting */ @@ -279,21 +277,14 @@ public class OutputFormat implements Cloneable { } /** - *

* This will set whether the text is output verbatim (false) or with * whitespace stripped as per {@link * org.dom4j.Element#getTextTrim()}. - *

- * - *

- *

- * - *

+ * * Default: false - *

- * + * * @param trimText - * boolean true=>trim the whitespace, false=>use + * boolean true → trim the whitespace, false → use * text verbatim */ public void setTrimText(boolean trimText) { @@ -305,7 +296,6 @@ public class OutputFormat implements Cloneable { } /** - *

* Ensure that text immediately preceded by or followed by an element will * be "padded" with a single space. This is used to allow make * browser-friendly HTML, avoiding trimText's transformation of, e.g., @@ -314,17 +304,12 @@ public class OutputFormat implements Cloneable { * (the latter will run the three separate words together into a single * word). This setting is not too useful if you haven't also called * {@link #setTrimText}. - *

- * - *

+ * * The padding string will only be added if the text itself starts or ends * with some whitespace characters. - *

- * - *

+ * * Default: false - *

- * + * * @param padText * boolean if true, pad string-element boundaries */ @@ -337,11 +322,10 @@ public class OutputFormat implements Cloneable { } /** - *

* This will set the indent String to use; this is usually a * String of empty spaces. If you pass null, or the empty * string (""), then no indentation will happen. - *

+ * * Default: none (null) * * @param indent @@ -372,12 +356,10 @@ public class OutputFormat implements Cloneable { } /** - *

* This will set the indent String's size; an indentSize of * 4 would result in the indention being equivalent to the * String "    " (four space characters). - *

- * + * * @param indentSize * int number of spaces in indentation. */ @@ -392,18 +374,14 @@ public class OutputFormat implements Cloneable { } /** - *

* Whether or not to use the XHTML standard: like HTML but passes an XML * parser with real, closed tags. Also, XHTML CDATA sections will be output * with the CDATA delimiters: ( " <![CDATA[ " and " * ]]> " ) otherwise, the class HTMLWriter will output the * CDATA text, but not the delimiters. - *

- * - *

+ * * Default is false - *

- * + * * @return DOCUMENT ME! */ public boolean isXHTML() { @@ -411,20 +389,16 @@ public class OutputFormat implements Cloneable { } /** - *

* This will set whether or not to use the XHTML standard: like HTML but * passes an XML parser with real, closed tags. Also, XHTML CDATA sections * will be output with the CDATA delimiters: ( " <[CDATA[ * " and " ]]< ) otherwise, the class HTMLWriter * will output the CDATA text, but not the delimiters. - *

- * - *

+ * * Default: false - *

- * + * * @param xhtml - * boolean true=>conform to XHTML, false=>conform + * boolean true → conform to XHTML, false → conform * to HTML, can have unclosed tags, etc. */ public void setXHTML(boolean xhtml) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/PruningElementStack.java b/fine-org-dom4j/src/main/java/org/dom4j/io/PruningElementStack.java index f53a28302..5d8ce416e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/PruningElementStack.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/PruningElementStack.java @@ -20,7 +20,7 @@ import org.dom4j.ElementHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ */ class PruningElementStack extends ElementStack { /** ElementHandler to call when pruning occurs */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXContentHandler.java b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXContentHandler.java index 0685727fb..cf40de5a7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXContentHandler.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXContentHandler.java @@ -21,10 +21,7 @@ import org.dom4j.Element; import org.dom4j.ElementHandler; import org.dom4j.Namespace; import org.dom4j.QName; -import org.dom4j.dtd.AttributeDecl; -import org.dom4j.dtd.ElementDecl; -import org.dom4j.dtd.ExternalEntityDecl; -import org.dom4j.dtd.InternalEntityDecl; +import org.dom4j.dtd.*; import org.dom4j.tree.AbstractElement; import org.dom4j.tree.NamespaceStack; @@ -37,6 +34,7 @@ import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.ext.DeclHandler; import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.ext.Locator2; import org.xml.sax.helpers.DefaultHandler; /** @@ -45,7 +43,7 @@ import org.xml.sax.helpers.DefaultHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.61 $ */ public class SAXContentHandler extends DefaultHandler implements LexicalHandler, DeclHandler, DTDHandler { @@ -82,17 +80,11 @@ public class SAXContentHandler extends DefaultHandler implements */ private StringBuffer cdataText; - /** namespaces that are available for use */ - private Map availableNamespaceMap = new HashMap(); - - /** declared namespaces that are not yet available for use */ - private List declaredNamespaceList = new ArrayList(); - /** internal DTD declarations */ - private List internalDTDDeclarations; + private List internalDTDDeclarations; /** external DTD declarations */ - private List externalDTDDeclarations; + private List externalDTDDeclarations; /** The number of namespaces that are declared in the current scope */ private int declaredNamespaceIndex; @@ -844,17 +836,8 @@ public class SAXContentHandler extends DefaultHandler implements return null; } - // use reflection to avoid dependency on Locator2 - // or other locator implemenations. - try { - Method m = locator.getClass().getMethod("getEncoding", - new Class[] {}); - - if (m != null) { - return (String) m.invoke(locator, null); - } - } catch (Exception e) { - // do nothing + if (locator instanceof Locator2) { + return ((Locator2) locator).getEncoding(); } // couldn't determine encoding, returning null... @@ -941,9 +924,9 @@ public class SAXContentHandler extends DefaultHandler implements * @param declaration * DOCUMENT ME! */ - protected void addDTDDeclaration(Object declaration) { + protected void addDTDDeclaration(Decl declaration) { if (internalDTDDeclarations == null) { - internalDTDDeclarations = new ArrayList(); + internalDTDDeclarations = new ArrayList(); } internalDTDDeclarations.add(declaration); @@ -955,9 +938,9 @@ public class SAXContentHandler extends DefaultHandler implements * @param declaration * DOCUMENT ME! */ - protected void addExternalDTDDeclaration(Object declaration) { + protected void addExternalDTDDeclaration(Decl declaration) { if (externalDTDDeclarations == null) { - externalDTDDeclarations = new ArrayList(); + externalDTDDeclarations = new ArrayList(); } externalDTDDeclarations.add(declaration); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXEventRecorder.java b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXEventRecorder.java index 2f791c34d..192a3e8aa 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXEventRecorder.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXEventRecorder.java @@ -67,9 +67,9 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, private static final byte NULL = 2; - private List events = new ArrayList(); + private List events = new ArrayList(); - private Map prefixMappings = new HashMap(); + private Map> prefixMappings = new HashMap>(); private static final String XMLNS = "xmlns"; @@ -79,11 +79,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, } public void replay(ContentHandler handler) throws SAXException { - SAXEvent saxEvent; - Iterator itr = events.iterator(); - - while (itr.hasNext()) { - saxEvent = (SAXEvent) itr.next(); + for (SAXEvent saxEvent : events) { switch (saxEvent.event) { // replay to ContentHandler @@ -117,13 +113,10 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, case SAXEvent.START_ELEMENT: AttributesImpl attributes = new AttributesImpl(); - List attParmList = (List) saxEvent.getParm(3); + List attParmList = (List) saxEvent.getParm(3); if (attParmList != null) { - Iterator attsItr = attParmList.iterator(); - - while (attsItr.hasNext()) { - String[] attParms = (String[]) attsItr.next(); + for (String[] attParms : attParmList) { attributes.addAttribute(attParms[0], attParms[1], attParms[2], attParms[3], attParms[4]); } @@ -145,8 +138,8 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, case SAXEvent.CHARACTERS: char[] chars = (char[]) saxEvent.getParm(0); - int start = ((Integer) saxEvent.getParm(1)).intValue(); - int end = ((Integer) saxEvent.getParm(2)).intValue(); + int start = (Integer) saxEvent.getParm(1); + int end = (Integer) saxEvent.getParm(2); handler.characters(chars, start, end); break; @@ -154,7 +147,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, // replay to LexicalHandler case SAXEvent.START_DTD: ((LexicalHandler) handler).startDTD((String) saxEvent - .getParm(0), (String) saxEvent.getParm(1), + .getParm(0), (String) saxEvent.getParm(1), (String) saxEvent.getParm(2)); break; @@ -189,8 +182,8 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, case SAXEvent.COMMENT: char[] cchars = (char[]) saxEvent.getParm(0); - int cstart = ((Integer) saxEvent.getParm(1)).intValue(); - int cend = ((Integer) saxEvent.getParm(2)).intValue(); + int cstart = (Integer) saxEvent.getParm(1); + int cend = (Integer) saxEvent.getParm(2); ((LexicalHandler) handler).comment(cchars, cstart, cend); break; @@ -204,7 +197,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, case SAXEvent.ATTRIBUTE_DECL: ((DeclHandler) handler).attributeDecl((String) saxEvent - .getParm(0), (String) saxEvent.getParm(1), + .getParm(0), (String) saxEvent.getParm(1), (String) saxEvent.getParm(2), (String) saxEvent .getParm(3), (String) saxEvent.getParm(4)); @@ -272,7 +265,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, saxEvent.addParm(localName); saxEvent.addParm(qualifiedName); - QName qName = null; + QName qName; if (namespaceURI != null) { qName = new QName(localName, Namespace.get(namespaceURI)); } else { @@ -280,8 +273,8 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, } if ((attributes != null) && (attributes.getLength() > 0)) { - List attParmList = new ArrayList(attributes.getLength()); - String[] attParms = null; + List attParmList = new ArrayList(attributes.getLength()); + String[] attParms; for (int i = 0; i < attributes.getLength(); i++) { @@ -292,7 +285,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, // if SAXWriter is writing a DOMDocument, namespace // decls are treated as attributes. record a start // prefix mapping event - String prefix = null; + String prefix; if (attLocalName.length() > 5) { prefix = attLocalName.substring(6); } else { @@ -307,9 +300,9 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, // 'register' the prefix so that we can generate // an end prefix mapping event within endElement - List prefixes = (List) prefixMappings.get(qName); + List prefixes = prefixMappings.get(qName); if (prefixes == null) { - prefixes = new ArrayList(); + prefixes = new ArrayList(); prefixMappings.put(qName, prefixes); } prefixes.add(prefix); @@ -346,20 +339,19 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, // check to see if a we issued a start prefix mapping event // for DOMDocument namespace decls - QName elementName = null; + QName elementName; if (namespaceURI != null) { elementName = new QName(localName, Namespace.get(namespaceURI)); } else { elementName = new QName(localName); } - List prefixes = (List) prefixMappings.get(elementName); + List prefixes = prefixMappings.get(elementName); if (prefixes != null) { - Iterator itr = prefixes.iterator(); - while (itr.hasNext()) { - SAXEvent prefixEvent = + for (String prefixe : prefixes) { + SAXEvent prefixEvent = new SAXEvent(SAXEvent.END_PREFIX_MAPPING); - prefixEvent.addParm(itr.next()); + prefixEvent.addParm(prefixe); events.add(prefixEvent); } } @@ -369,8 +361,8 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, public void characters(char[] ch, int start, int end) throws SAXException { SAXEvent saxEvent = new SAXEvent(SAXEvent.CHARACTERS); saxEvent.addParm(ch); - saxEvent.addParm(new Integer(start)); - saxEvent.addParm(new Integer(end)); + saxEvent.addParm(start); + saxEvent.addParm(end); events.add(saxEvent); } @@ -415,8 +407,8 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, public void comment(char[] ch, int start, int end) throws SAXException { SAXEvent saxEvent = new SAXEvent(SAXEvent.COMMENT); saxEvent.addParm(ch); - saxEvent.addParm(new Integer(start)); - saxEvent.addParm(new Integer(end)); + saxEvent.addParm(start); + saxEvent.addParm(end); events.add(saxEvent); } @@ -469,7 +461,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException { if (in.readByte() != NULL) { - events = (List) in.readObject(); + events = (List) in.readObject(); } } @@ -518,7 +510,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, protected byte event; - protected List parms; + protected List parms; public SAXEvent() { } @@ -529,7 +521,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, void addParm(Object parm) { if (parms == null) { - parms = new ArrayList(3); + parms = new ArrayList(3); } parms.add(parm); @@ -559,7 +551,7 @@ public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, event = in.readByte(); if (in.readByte() != NULL) { - parms = (List) in.readObject(); + parms = (List) in.readObject(); } } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXHelper.java b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXHelper.java index 6ff56312d..e66905e9d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXHelper.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXHelper.java @@ -13,14 +13,16 @@ import org.xml.sax.SAXNotSupportedException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; +import javax.xml.parsers.SAXParserFactory; + /** *

* SAXHelper contains some helper methods for working with SAX * and XMLReader objects. *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.18 $ */ class SAXHelper { private static boolean loggedWarning = true; @@ -61,12 +63,21 @@ class SAXHelper { /** * Creats a default XMLReader via the org.xml.sax.driver system property or * JAXP if the system property is not set. - * + * + * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. + * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: + * + *
+     * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+     * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+     * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+     * 
+ * * @param validating * DOCUMENT ME! - * + * * @return DOCUMENT ME! - * + * * @throws SAXException * DOCUMENT ME! */ @@ -103,6 +114,21 @@ class SAXHelper { throw new SAXException("Couldn't create SAX reader"); } + // configure namespace support + SAXHelper.setParserFeature(reader, "http://xml.org/sax/features/namespaces", true); + SAXHelper.setParserFeature(reader, "http://xml.org/sax/features/namespace-prefixes", false); + + // external entites + SAXHelper.setParserFeature(reader, "http://xml.org/sax/properties/external-general-entities", false); + SAXHelper.setParserFeature(reader, "http://xml.org/sax/properties/external-parameter-entities", false); + + // external DTD + SAXHelper.setParserFeature(reader,"http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + + + // use Locator2 if possible + SAXHelper.setParserFeature(reader,"http://xml.org/sax/features/use-locator2", true); + return reader; } @@ -110,12 +136,12 @@ class SAXHelper { * This method attempts to use JAXP to locate the SAX2 XMLReader * implementation. This method uses reflection to avoid being dependent * directly on the JAXP classes. - * + * * @param validating * DOCUMENT ME! * @param namespaceAware * DOCUMENT ME! - * + * * @return DOCUMENT ME! */ protected static XMLReader createXMLReaderViaJAXP(boolean validating, @@ -161,24 +187,24 @@ class SAXHelper { * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided that the * following conditions are met: - * + * * 1. Redistributions of source code must retain copyright statements and * notices. Redistributions must also contain a copy of this document. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. The name "DOM4J" must not be used to endorse or promote products derived * from this Software without prior written permission of MetaStuff, Ltd. For * written permission, please contact dom4j-info@metastuff.com. - * + * * 4. Products derived from this Software may not be called "DOM4J" nor may * "DOM4J" appear in their names without prior written permission of MetaStuff, * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * + * * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * + * * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -190,6 +216,6 @@ class SAXHelper { * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXModifier.java b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXModifier.java index 818fe42b4..71777f321 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXModifier.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXModifier.java @@ -50,7 +50,7 @@ public class SAXModifier { private SAXModifyReader modifyReader; - private HashMap modifiers = new HashMap(); + private HashMap modifiers = new HashMap(); /** * Creates a new modifier.
@@ -102,7 +102,7 @@ public class SAXModifier { /** * Reads a Document from the given {@link java.io.File}and writes it to the - * specified {@link XMLWriter}using SAX. Registered {@linkElementModifier} + * specified {@link XMLWriter}using SAX. Registered {@link ElementModifier} * objects are invoked on the fly. * * @param source @@ -246,7 +246,7 @@ public class SAXModifier { /** * Reads a Document from the given {@link java.net.URL}and writes it to the - * specified {@link XMLWriter}using SAX. Registered {@linkElementModifier} + * specified {@link XMLWriter}using SAX. Registered {@link ElementModifier} * objects are invoked on the fly. * * @param source @@ -269,7 +269,7 @@ public class SAXModifier { /** * Reads a Document from the given URL or filename and writes it to the - * specified {@link XMLWriter}using SAX. Registered {@linkElementModifier} + * specified {@link XMLWriter}using SAX. Registered {@link ElementModifier} * objects are invoked on the fly. * * @param source @@ -385,14 +385,10 @@ public class SAXModifier { reader.resetHandlers(); - Iterator modifierIt = this.modifiers.entrySet().iterator(); - - while (modifierIt.hasNext()) { - Map.Entry entry = (Map.Entry) modifierIt.next(); - + for (Map.Entry entry : this.modifiers.entrySet()) { SAXModifyElementHandler handler = new SAXModifyElementHandler( - (ElementModifier) entry.getValue()); - reader.addHandler((String) entry.getKey(), handler); + entry.getValue()); + reader.addHandler(entry.getKey(), handler); } reader.setXMLWriter(getXMLWriter()); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXReader.java b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXReader.java index cfcdaa81f..73660abff 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXReader.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXReader.java @@ -30,1002 +30,981 @@ import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.XMLReaderFactory; +import javax.xml.parsers.SAXParserFactory; + /** - *

* SAXReader creates a DOM4J tree from SAX parsing events. - *

- * *

* The actual SAX parser that is used by this class is configurable so you can * use your favourite SAX parser if you wish. DOM4J comes configured with its * own SAX parser so you do not need to worry about configuring the SAX parser. - *

- * *

* To explicitly configure the SAX parser that is used via Java code you can use * a constructor or use the {@link #setXMLReader(XMLReader)}or {@link * #setXMLReaderClassName(String)} methods. - *

- * *

* If the parser is not specified explicitly then the standard SAX policy of * using the org.xml.sax.driver system property is used to * determine the implementation class of {@link XMLReader}. - *

- * *

* If the org.xml.sax.driver system property is not defined then * JAXP is used via reflection (so that DOM4J is not explicitly dependent on the * JAXP classes) to load the JAXP configured SAXParser. If there is any error * creating a JAXP SAXParser an informational message is output and then the * default (Aelfred) SAX parser is used instead. - *

- * *

* If you are trying to use JAXP to explicitly set your SAX parser and are * experiencing problems, you can turn on verbose error reporting by defining * the system property org.dom4j.verbose to be "true" which will * output a more detailed description of why JAXP could not find a SAX parser - *

- * *

* For more information on JAXP please go to Sun's Java & XML site - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.58 $ */ public class SAXReader { - private static final String SAX_STRING_INTERNING = - "http://xml.org/sax/features/string-interning"; - private static final String SAX_NAMESPACE_PREFIXES = - "http://xml.org/sax/features/namespace-prefixes"; - private static final String SAX_NAMESPACES = - "http://xml.org/sax/features/namespaces"; - private static final String SAX_DECL_HANDLER = - "http://xml.org/sax/properties/declaration-handler"; - private static final String SAX_LEXICAL_HANDLER = - "http://xml.org/sax/properties/lexical-handler"; - private static final String SAX_LEXICALHANDLER = - "http://xml.org/sax/handlers/LexicalHandler"; - - /** DocumentFactory used to create new document objects */ - private DocumentFactory factory; - - /** XMLReader used to parse the SAX events */ - private XMLReader xmlReader; - - /** Whether validation should occur */ - private boolean validating; - - /** DispatchHandler to call when each Element is encountered */ - private DispatchHandler dispatchHandler; - - /** ErrorHandler class to use */ - private ErrorHandler errorHandler; - - /** The entity resolver */ - private EntityResolver entityResolver; - - /** Should element & attribute names and namespace URIs be interned? */ - private boolean stringInternEnabled = true; - - /** Should internal DTD declarations be expanded into a List in the DTD */ - private boolean includeInternalDTDDeclarations = false; - - /** Should external DTD declarations be expanded into a List in the DTD */ - private boolean includeExternalDTDDeclarations = false; - - /** Whether adjacent text nodes should be merged */ - private boolean mergeAdjacentText = false; - - /** Holds value of property stripWhitespaceText. */ - private boolean stripWhitespaceText = false; - - /** Should we ignore comments */ - private boolean ignoreComments = false; - - /** Encoding of InputSource - null means system default encoding */ - private String encoding = null; - - // private boolean includeExternalGeneralEntities = false; - // private boolean includeExternalParameterEntities = false; - - /** The SAX filter used to filter SAX events */ - private XMLFilter xmlFilter; - - public SAXReader() { - } - - public SAXReader(boolean validating) { - this.validating = validating; - } - - public SAXReader(DocumentFactory factory) { - this.factory = factory; - } - - public SAXReader(DocumentFactory factory, boolean validating) { - this.factory = factory; - this.validating = validating; - } - - public SAXReader(XMLReader xmlReader) { - this.xmlReader = xmlReader; - } - - public SAXReader(XMLReader xmlReader, boolean validating) { - this.xmlReader = xmlReader; - this.validating = validating; - } - - public SAXReader(String xmlReaderClassName) throws SAXException { - if (xmlReaderClassName != null) { - this.xmlReader = XMLReaderFactory - .createXMLReader(xmlReaderClassName); + private static final String SAX_STRING_INTERNING = + "http://xml.org/sax/features/string-interning"; + private static final String SAX_DECL_HANDLER = + "http://xml.org/sax/properties/declaration-handler"; + private static final String SAX_LEXICAL_HANDLER = + "http://xml.org/sax/properties/lexical-handler"; + private static final String SAX_LEXICALHANDLER = + "http://xml.org/sax/handlers/LexicalHandler"; + + /** + * DocumentFactory used to create new document objects + */ + private DocumentFactory factory; + + /** + * XMLReader used to parse the SAX events + */ + private XMLReader xmlReader; + + /** + * Whether validation should occur + */ + private boolean validating; + + /** + * DispatchHandler to call when each Element is encountered + */ + private DispatchHandler dispatchHandler; + + /** + * ErrorHandler class to use + */ + private ErrorHandler errorHandler; + + /** + * The entity resolver + */ + private EntityResolver entityResolver; + + /** + * Should element & attribute names and namespace URIs be interned? + */ + private boolean stringInternEnabled = true; + + /** + * Should internal DTD declarations be expanded into a List in the DTD + */ + private boolean includeInternalDTDDeclarations = false; + + /** + * Should external DTD declarations be expanded into a List in the DTD + */ + private boolean includeExternalDTDDeclarations = false; + + /** + * Whether adjacent text nodes should be merged + */ + private boolean mergeAdjacentText = false; + + /** + * Holds value of property stripWhitespaceText. + */ + private boolean stripWhitespaceText = false; + + /** + * Should we ignore comments + */ + private boolean ignoreComments = false; + + /** + * Encoding of InputSource - null means system default encoding + */ + private String encoding = null; + + // private boolean includeExternalGeneralEntities = false; + // private boolean includeExternalParameterEntities = false; + + /** + * The SAX filter used to filter SAX events + * + * @since 2.1.2 + */ + private XMLFilter xmlFilter; + + public static SAXReader createDefault() { + SAXReader reader = new SAXReader(); + try { + reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + reader.setFeature("http://xml.org/sax/features/external-general-entities", false); + reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } catch (SAXException e) { + // nothing to do, incompatible reader + } + return reader; + } + + /** + * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. + * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: + * + *
+   * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+   * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+   * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+   * 
+ */ + public SAXReader() { + } + + /** + * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. + * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: + * + *
+   * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+   * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+   * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+   * 
+ * + * @param validating + */ + public SAXReader(boolean validating) { + this.validating = validating; + } + + /** + * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. + * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: + * + *
+   * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+   * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+   * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+   * 
+ * + * @param factory + */ + public SAXReader(DocumentFactory factory) { + this.factory = factory; + } + + /** + * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. + * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: + * + *
+   * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+   * reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+   * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+   * 
+ * + * @param factory + * @param validating + */ + public SAXReader(DocumentFactory factory, boolean validating) { + this.factory = factory; + this.validating = validating; + } + + public SAXReader(XMLReader xmlReader) { + this.xmlReader = xmlReader; + } + + public SAXReader(XMLReader xmlReader, boolean validating) { + this.xmlReader = xmlReader; + this.validating = validating; + } + + public SAXReader(String xmlReaderClassName) throws SAXException { + if (xmlReaderClassName != null) { + this.xmlReader = XMLReaderFactory + .createXMLReader(xmlReaderClassName); + } + } + + public SAXReader(String xmlReaderClassName, boolean validating) + throws SAXException { + if (xmlReaderClassName != null) { + this.xmlReader = XMLReaderFactory + .createXMLReader(xmlReaderClassName); + } + + this.validating = validating; + } + + /** + * Allows a SAX property to be set on the underlying SAX parser. This can be + * useful to set parser-specific properties such as the location of schema + * or DTD resources. Though use this method with caution as it has the + * possibility of breaking the standard behaviour. An alternative to calling + * this method is to correctly configure an XMLReader object instance and + * call the {@link #setXMLReader(XMLReader)}method + * + * @param name is the SAX property name + * @param value is the value of the SAX property + * @throws SAXException if the XMLReader could not be created or the property could + * not be changed. + */ + public void setProperty(String name, Object value) throws SAXException { + getXMLReader().setProperty(name, value); + } + + /** + * Sets a SAX feature on the underlying SAX parser. This can be useful to + * set parser-specific features. Though use this method with caution as it + * has the possibility of breaking the standard behaviour. An alternative to + * calling this method is to correctly configure an XMLReader object + * instance and call the {@link #setXMLReader(XMLReader)}method + * + * @param name is the SAX feature name + * @param value is the value of the SAX feature + * @throws SAXException if the XMLReader could not be created or the feature could + * not be changed. + */ + public void setFeature(String name, boolean value) throws SAXException { + getXMLReader().setFeature(name, value); + } + + /** + *

+ * Reads a Document from the given File + *

+ * + * @param file is the File to read from. + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(File file) throws DocumentException { + try { + /* + * We cannot convert the file to an URL because if the filename + * contains '#' characters, there will be problems with the URL in + * the InputSource (because a URL like + * http://myhost.com/index#anchor is treated the same as + * http://myhost.com/index) Thanks to Christian Oetterli + */ + InputSource source = new InputSource(new FileInputStream(file)); + if (this.encoding != null) { + source.setEncoding(this.encoding); + } + String path = file.getAbsolutePath(); + + if (path != null) { + // Code taken from Ant FileUtils + StringBuffer sb = new StringBuffer("file://"); + + // add an extra slash for filesystems with drive-specifiers + if (!path.startsWith(File.separator)) { + sb.append("/"); } - } - public SAXReader(String xmlReaderClassName, boolean validating) - throws SAXException { - if (xmlReaderClassName != null) { - this.xmlReader = XMLReaderFactory - .createXMLReader(xmlReaderClassName); + path = path.replace('\\', '/'); + sb.append(path); + + source.setSystemId(sb.toString()); + } + + return read(source); + } catch (FileNotFoundException e) { + throw new DocumentException(e.getMessage(), e); + } + } + + /** + *

+ * Reads a Document from the given URL using SAX + *

+ * + * @param url URL to read from. + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(URL url) throws DocumentException { + String systemID = url.toExternalForm(); + + InputSource source = new InputSource(systemID); + if (this.encoding != null) { + source.setEncoding(this.encoding); + } + + return read(source); + } + + /** + *

+ * Reads a Document from the given URL or filename using SAX. + *

+ * + *

+ * If the systemId contains a ':' character then it is + * assumed to be a URL otherwise its assumed to be a file name. If you want + * finer grained control over this mechansim then please explicitly pass in + * either a {@link URL}or a {@link File}instance instead of a {@link + * String} to denote the source of the document. + *

+ * + * @param systemId is a URL for a document or a file name. + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(String systemId) throws DocumentException { + InputSource source = new InputSource(systemId); + if (this.encoding != null) { + source.setEncoding(this.encoding); + } + + return read(source); + } + + /** + *

+ * Reads a Document from the given stream using SAX + *

+ * + * @param in InputStream to read from. + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(InputStream in) throws DocumentException { + InputSource source = new InputSource(in); + if (this.encoding != null) { + source.setEncoding(this.encoding); + } + + return read(source); + } + + /** + * Reads a Document from the given Reader using SAX + * + * @param reader is the reader for the input + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(Reader reader) throws DocumentException { + InputSource source = new InputSource(reader); + if (this.encoding != null) { + source.setEncoding(this.encoding); + } + + return read(source); + } + + /** + *

+ * Reads a Document from the given stream using SAX + *

+ * + * @param in InputStream to read from. + * @param systemId is the URI for the input + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(InputStream in, String systemId) + throws DocumentException { + InputSource source = new InputSource(in); + source.setSystemId(systemId); + if (this.encoding != null) { + source.setEncoding(this.encoding); + } + + return read(source); + } + + /** + *

+ * Reads a Document from the given Reader using SAX + *

+ * + * @param reader is the reader for the input + * @param systemId is the URI for the input + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(Reader reader, String systemId) + throws DocumentException { + InputSource source = new InputSource(reader); + source.setSystemId(systemId); + if (this.encoding != null) { + source.setEncoding(this.encoding); + } + + return read(source); + } + + /** + *

+ * Reads a Document from the given InputSource using SAX + *

+ * + * @param in InputSource to read from. + * @return the newly created Document instance + * @throws DocumentException if an error occurs during parsing. + */ + public Document read(InputSource in) throws DocumentException { + try { + XMLReader reader = getXMLReader(); + + reader = installXMLFilter(reader); + + EntityResolver thatEntityResolver = this.entityResolver; + + if (thatEntityResolver == null) { + thatEntityResolver = createDefaultEntityResolver(in + .getSystemId()); + this.entityResolver = thatEntityResolver; + } + + reader.setEntityResolver(thatEntityResolver); + + SAXContentHandler contentHandler = createContentHandler(reader); + contentHandler.setEntityResolver(thatEntityResolver); + contentHandler.setInputSource(in); + + boolean internal = isIncludeInternalDTDDeclarations(); + boolean external = isIncludeExternalDTDDeclarations(); + + contentHandler.setIncludeInternalDTDDeclarations(internal); + contentHandler.setIncludeExternalDTDDeclarations(external); + contentHandler.setMergeAdjacentText(isMergeAdjacentText()); + contentHandler.setStripWhitespaceText(isStripWhitespaceText()); + contentHandler.setIgnoreComments(isIgnoreComments()); + reader.setContentHandler(contentHandler); + + configureReader(reader, contentHandler); + + reader.parse(in); + + return contentHandler.getDocument(); + } catch (Exception e) { + if (e instanceof SAXParseException) { + // e.printStackTrace(); + SAXParseException parseException = (SAXParseException) e; + String systemId = parseException.getSystemId(); + + if (systemId == null) { + systemId = ""; } - this.validating = validating; - } - - /** - * Allows a SAX property to be set on the underlying SAX parser. This can be - * useful to set parser-specific properties such as the location of schema - * or DTD resources. Though use this method with caution as it has the - * possibility of breaking the standard behaviour. An alternative to calling - * this method is to correctly configure an XMLReader object instance and - * call the {@link #setXMLReader(XMLReader)}method - * - * @param name - * is the SAX property name - * @param value - * is the value of the SAX property - * - * @throws SAXException - * if the XMLReader could not be created or the property could - * not be changed. - */ - public void setProperty(String name, Object value) throws SAXException { - getXMLReader().setProperty(name, value); - } - - /** - * Sets a SAX feature on the underlying SAX parser. This can be useful to - * set parser-specific features. Though use this method with caution as it - * has the possibility of breaking the standard behaviour. An alternative to - * calling this method is to correctly configure an XMLReader object - * instance and call the {@link #setXMLReader(XMLReader)}method - * - * @param name - * is the SAX feature name - * @param value - * is the value of the SAX feature - * - * @throws SAXException - * if the XMLReader could not be created or the feature could - * not be changed. - */ - public void setFeature(String name, boolean value) throws SAXException { - getXMLReader().setFeature(name, value); - } - - /** - *

- * Reads a Document from the given File - *

- * - * @param file - * is the File to read from. - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(File file) throws DocumentException { - try { - /* - * We cannot convert the file to an URL because if the filename - * contains '#' characters, there will be problems with the URL in - * the InputSource (because a URL like - * http://myhost.com/index#anchor is treated the same as - * http://myhost.com/index) Thanks to Christian Oetterli - */ - InputSource source = new InputSource(new FileInputStream(file)); - if (this.encoding != null) { - source.setEncoding(this.encoding); - } - String path = file.getAbsolutePath(); - - if (path != null) { - // Code taken from Ant FileUtils - StringBuffer sb = new StringBuffer("file://"); - - // add an extra slash for filesystems with drive-specifiers - if (!path.startsWith(File.separator)) { - sb.append("/"); - } - - path = path.replace('\\', '/'); - sb.append(path); - - source.setSystemId(sb.toString()); - } - - return read(source); - } catch (FileNotFoundException e) { - throw new DocumentException(e.getMessage(), e); + String message = "Error on line " + + parseException.getLineNumber() + " of document " + + systemId + " : " + parseException.getMessage(); + + throw new DocumentException(message, e); + } else { + throw new DocumentException(e.getMessage(), e); + } + } + } + + // Properties + // ------------------------------------------------------------------------- + + /** + * DOCUMENT ME! + * + * @return the validation mode, true if validating will be done otherwise + * false. + */ + public boolean isValidating() { + return validating; + } + + /** + * Sets the validation mode. + * + * @param validation indicates whether or not validation should occur. + */ + public void setValidation(boolean validation) { + this.validating = validation; + } + + /** + * DOCUMENT ME! + * + * @return whether internal DTD declarations should be expanded into the + * DocumentType object or not. + */ + public boolean isIncludeInternalDTDDeclarations() { + return includeInternalDTDDeclarations; + } + + /** + * Sets whether internal DTD declarations should be expanded into the + * DocumentType object or not. + * + * @param include whether or not DTD declarations should be expanded and + * included into the DocumentType object. + */ + public void setIncludeInternalDTDDeclarations(boolean include) { + this.includeInternalDTDDeclarations = include; + } + + /** + * DOCUMENT ME! + * + * @return whether external DTD declarations should be expanded into the + * DocumentType object or not. + */ + public boolean isIncludeExternalDTDDeclarations() { + return includeExternalDTDDeclarations; + } + + /** + * Sets whether DTD external declarations should be expanded into the + * DocumentType object or not. + * + * @param include whether or not DTD declarations should be expanded and + * included into the DocumentType object. + */ + public void setIncludeExternalDTDDeclarations(boolean include) { + this.includeExternalDTDDeclarations = include; + } + + /** + * Sets whether String interning is enabled or disabled for element & + * attribute names and namespace URIs. This proprety is enabled by default. + * + * @return DOCUMENT ME! + */ + public boolean isStringInternEnabled() { + return stringInternEnabled; + } + + /** + * Sets whether String interning is enabled or disabled for element & + * attribute names and namespace URIs + * + * @param stringInternEnabled DOCUMENT ME! + */ + public void setStringInternEnabled(boolean stringInternEnabled) { + this.stringInternEnabled = stringInternEnabled; + } + + /** + * Returns whether adjacent text nodes should be merged together. + * + * @return Value of property mergeAdjacentText. + */ + public boolean isMergeAdjacentText() { + return mergeAdjacentText; + } + + /** + * Sets whether or not adjacent text nodes should be merged together when + * parsing. + * + * @param mergeAdjacentText New value of property mergeAdjacentText. + */ + public void setMergeAdjacentText(boolean mergeAdjacentText) { + this.mergeAdjacentText = mergeAdjacentText; + } + + /** + * Sets whether whitespace between element start and end tags should be + * ignored + * + * @return Value of property stripWhitespaceText. + */ + public boolean isStripWhitespaceText() { + return stripWhitespaceText; + } + + /** + * Sets whether whitespace between element start and end tags should be + * ignored. + * + * @param stripWhitespaceText New value of property stripWhitespaceText. + */ + public void setStripWhitespaceText(boolean stripWhitespaceText) { + this.stripWhitespaceText = stripWhitespaceText; + } + + /** + * Returns whether we should ignore comments or not. + * + * @return boolean + */ + public boolean isIgnoreComments() { + return ignoreComments; + } + + /** + * Sets whether we should ignore comments or not. + * + * @param ignoreComments whether we should ignore comments or not. + */ + public void setIgnoreComments(boolean ignoreComments) { + this.ignoreComments = ignoreComments; + } + + /** + * DOCUMENT ME! + * + * @return the DocumentFactory used to create document + * objects + */ + public DocumentFactory getDocumentFactory() { + if (factory == null) { + factory = DocumentFactory.getInstance(); + } + + return factory; + } + + /** + *

+ * This sets the DocumentFactory used to create new + * documents. This method allows the building of custom DOM4J tree objects + * to be implemented easily using a custom derivation of + * {@link DocumentFactory} + *

+ * + * @param documentFactory DocumentFactory used to create DOM4J objects + */ + public void setDocumentFactory(DocumentFactory documentFactory) { + this.factory = documentFactory; + } + + /** + * DOCUMENT ME! + * + * @return the ErrorHandler used by SAX + */ + public ErrorHandler getErrorHandler() { + return errorHandler; + } + + /** + * Sets the ErrorHandler used by the SAX + * XMLReader. + * + * @param errorHandler is the ErrorHandler used by SAX + */ + public void setErrorHandler(ErrorHandler errorHandler) { + this.errorHandler = errorHandler; + } + + /** + * Returns the current entity resolver used to resolve entities + * + * @return DOCUMENT ME! + */ + public EntityResolver getEntityResolver() { + return entityResolver; + } + + /** + * Sets the entity resolver used to resolve entities. + * + * @param entityResolver DOCUMENT ME! + */ + public void setEntityResolver(EntityResolver entityResolver) { + this.entityResolver = entityResolver; + } + + /** + * DOCUMENT ME! + * + * @return the XMLReader used to parse SAX events + * @throws SAXException DOCUMENT ME! + */ + public XMLReader getXMLReader() throws SAXException { + if (xmlReader == null) { + xmlReader = createXMLReader(); + } + + return xmlReader; + } + + /** + * Sets the XMLReader used to parse SAX events + * + * @param reader is the XMLReader to parse SAX events + */ + public void setXMLReader(XMLReader reader) { + this.xmlReader = reader; + } + + /** + * Returns encoding used for InputSource (null means system default + * encoding) + * + * @return encoding used for InputSource + */ + public String getEncoding() { + return encoding; + } + + /** + * Sets encoding used for InputSource (null means system default encoding) + * + * @param encoding is encoding used for InputSource + */ + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + /** + * Sets the class name of the XMLReader to be used to parse + * SAX events. + * + * @param xmlReaderClassName is the class name of the XMLReader to parse SAX + * events + * @throws SAXException DOCUMENT ME! + */ + public void setXMLReaderClassName(String xmlReaderClassName) + throws SAXException { + setXMLReader(XMLReaderFactory.createXMLReader(xmlReaderClassName)); + } + + /** + * Adds the ElementHandler to be called when the specified + * path is encounted. + * + * @param path is the path to be handled + * @param handler is the ElementHandler to be called by the event + * based processor. + */ + public void addHandler(String path, ElementHandler handler) { + getDispatchHandler().addHandler(path, handler); + } + + /** + * Removes the ElementHandler from the event based processor, + * for the specified path. + * + * @param path is the path to remove the ElementHandler for. + */ + public void removeHandler(String path) { + getDispatchHandler().removeHandler(path); + } + + /** + * When multiple ElementHandler instances have been + * registered, this will set a default ElementHandler to be + * called for any path which does NOT have a handler registered. + * + * @param handler is the ElementHandler to be called by the event + * based processor. + */ + public void setDefaultHandler(ElementHandler handler) { + getDispatchHandler().setDefaultHandler(handler); + } + + /** + * This method clears out all the existing handlers and default handler + * setting things back as if no handler existed. Useful when reusing an + * object instance. + */ + public void resetHandlers() { + getDispatchHandler().resetHandlers(); + } + + /** + * Returns the SAX filter being used to filter SAX events. + * + * @return the SAX filter being used or null if no SAX filter is installed + */ + public XMLFilter getXMLFilter() { + return xmlFilter; + } + + /** + * Sets the SAX filter to be used when filtering SAX events + * + * @param filter is the SAX filter to use or null to disable filtering + */ + public void setXMLFilter(XMLFilter filter) { + this.xmlFilter = filter; + } + + // Implementation methods + // ------------------------------------------------------------------------- + + /** + * Installs any XMLFilter objects required to allow the SAX event stream to + * be filtered and preprocessed before it gets to dom4j. + * + * @param reader DOCUMENT ME! + * @return the new XMLFilter if applicable or the original XMLReader if no + * filter is being used. + */ + protected XMLReader installXMLFilter(XMLReader reader) { + XMLFilter filter = getXMLFilter(); + + if (filter != null) { + // find the root XMLFilter + XMLFilter root = filter; + + while (true) { + XMLReader parent = root.getParent(); + + if (parent instanceof XMLFilter) { + root = (XMLFilter) parent; + } else { + break; } + } + + root.setParent(reader); + + return filter; } - /** - *

- * Reads a Document from the given URL using SAX - *

- * - * @param url - * URL to read from. - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(URL url) throws DocumentException { - String systemID = url.toExternalForm(); - - InputSource source = new InputSource(systemID); - if (this.encoding != null) { - source.setEncoding(this.encoding); - } + return reader; + } - return read(source); - } - - /** - *

- * Reads a Document from the given URL or filename using SAX. - *

- * - *

- * If the systemId contains a ':' character then it is - * assumed to be a URL otherwise its assumed to be a file name. If you want - * finer grained control over this mechansim then please explicitly pass in - * either a {@link URL}or a {@link File}instance instead of a {@link - * String} to denote the source of the document. - *

- * - * @param systemId - * is a URL for a document or a file name. - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(String systemId) throws DocumentException { - InputSource source = new InputSource(systemId); - if (this.encoding != null) { - source.setEncoding(this.encoding); + protected DispatchHandler getDispatchHandler() { + if (dispatchHandler == null) { + dispatchHandler = new DispatchHandler(); + } + + return dispatchHandler; + } + + protected void setDispatchHandler(DispatchHandler dispatchHandler) { + this.dispatchHandler = dispatchHandler; + } + + /** + * Factory Method to allow alternate methods of creating and configuring + * XMLReader objects + * + * @return DOCUMENT ME! + * @throws SAXException DOCUMENT ME! + */ + protected XMLReader createXMLReader() throws SAXException { + return SAXHelper.createXMLReader(isValidating()); + } + + /** + * Configures the XMLReader before use + * + * @param reader DOCUMENT ME! + * @param handler DOCUMENT ME! + * @throws DocumentException DOCUMENT ME! + */ + protected void configureReader(XMLReader reader, DefaultHandler handler) + throws DocumentException { + // configure lexical handling + SAXHelper.setParserProperty(reader, SAX_LEXICALHANDLER, handler); + + // try alternate property just in case + SAXHelper.setParserProperty(reader, SAX_LEXICAL_HANDLER, handler); + + // register the DeclHandler + if (includeInternalDTDDeclarations || includeExternalDTDDeclarations) { + SAXHelper.setParserProperty(reader, SAX_DECL_HANDLER, handler); + } + + // string interning + SAXHelper.setParserFeature(reader, SAX_STRING_INTERNING, + isStringInternEnabled()); + + try { + // configure validation support + reader.setFeature("http://xml.org/sax/features/validation", + isValidating()); + + if (errorHandler != null) { + reader.setErrorHandler(errorHandler); + } else { + reader.setErrorHandler(handler); + } + } catch (Exception e) { + if (isValidating()) { + throw new DocumentException("Validation not supported for" + + " XMLReader: " + reader, e); + } + } + } + + /** + * Factory Method to allow user derived SAXContentHandler objects to be used + * + * @param reader DOCUMENT ME! + * @return DOCUMENT ME! + */ + protected SAXContentHandler createContentHandler(XMLReader reader) { + return new SAXContentHandler(getDocumentFactory(), dispatchHandler); + } + + protected EntityResolver createDefaultEntityResolver(String systemId) { + String prefix = null; + + if ((systemId != null) && (systemId.length() > 0)) { + int idx = systemId.lastIndexOf('/'); + + if (idx > 0) { + prefix = systemId.substring(0, idx + 1); + } + } + + return new SAXEntityResolver(prefix); + } + + protected static class SAXEntityResolver implements EntityResolver, + Serializable { + protected String uriPrefix; + + public SAXEntityResolver(String uriPrefix) { + this.uriPrefix = uriPrefix; + } + + public InputSource resolveEntity(String publicId, String systemId) { + // try create a relative URI reader... + if ((systemId != null) && (systemId.length() > 0)) { + if ((uriPrefix != null) && (systemId.indexOf(':') <= 0)) { + systemId = uriPrefix + systemId; } + } - return read(source); - } - - /** - *

- * Reads a Document from the given stream using SAX - *

- * - * @param in - * InputStream to read from. - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(InputStream in) throws DocumentException { - InputSource source = new InputSource(in); - if (this.encoding != null) { - source.setEncoding(this.encoding); - } - - return read(source); - } - - /** - *

- * Reads a Document from the given Reader using SAX - *

- * - * @param reader - * is the reader for the input - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(Reader reader) throws DocumentException { - InputSource source = new InputSource(reader); - if (this.encoding != null) { - source.setEncoding(this.encoding); - } - - return read(source); - } - - /** - *

- * Reads a Document from the given stream using SAX - *

- * - * @param in - * InputStream to read from. - * @param systemId - * is the URI for the input - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(InputStream in, String systemId) - throws DocumentException { - InputSource source = new InputSource(in); - source.setSystemId(systemId); - if (this.encoding != null) { - source.setEncoding(this.encoding); - } - - return read(source); - } - - /** - *

- * Reads a Document from the given Reader using SAX - *

- * - * @param reader - * is the reader for the input - * @param systemId - * is the URI for the input - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(Reader reader, String systemId) - throws DocumentException { - InputSource source = new InputSource(reader); - source.setSystemId(systemId); - if (this.encoding != null) { - source.setEncoding(this.encoding); - } - - return read(source); - } - - /** - *

- * Reads a Document from the given InputSource using SAX - *

- * - * @param in - * InputSource to read from. - * - * @return the newly created Document instance - * - * @throws DocumentException - * if an error occurs during parsing. - */ - public Document read(InputSource in) throws DocumentException { - try { - XMLReader reader = getXMLReader(); - - reader = installXMLFilter(reader); - - EntityResolver thatEntityResolver = this.entityResolver; - - if (thatEntityResolver == null) { - thatEntityResolver = createDefaultEntityResolver(in - .getSystemId()); - this.entityResolver = thatEntityResolver; - } - - reader.setEntityResolver(thatEntityResolver); - - SAXContentHandler contentHandler = createContentHandler(reader); - contentHandler.setEntityResolver(thatEntityResolver); - contentHandler.setInputSource(in); - - boolean internal = isIncludeInternalDTDDeclarations(); - boolean external = isIncludeExternalDTDDeclarations(); - - contentHandler.setIncludeInternalDTDDeclarations(internal); - contentHandler.setIncludeExternalDTDDeclarations(external); - contentHandler.setMergeAdjacentText(isMergeAdjacentText()); - contentHandler.setStripWhitespaceText(isStripWhitespaceText()); - contentHandler.setIgnoreComments(isIgnoreComments()); - reader.setContentHandler(contentHandler); - - configureReader(reader, contentHandler); - - reader.parse(in); - - return contentHandler.getDocument(); - } catch (Exception e) { - if (e instanceof SAXParseException) { - // e.printStackTrace(); - SAXParseException parseException = (SAXParseException) e; - String systemId = parseException.getSystemId(); - - if (systemId == null) { - systemId = ""; - } - - String message = "Error on line " - + parseException.getLineNumber() + " of document " - + systemId + " : " + parseException.getMessage(); - - throw new DocumentException(message, e); - } else { - throw new DocumentException(e.getMessage(), e); - } - } - } - - // Properties - // ------------------------------------------------------------------------- - - /** - * DOCUMENT ME! - * - * @return the validation mode, true if validating will be done otherwise - * false. - */ - public boolean isValidating() { - return validating; - } - - /** - * Sets the validation mode. - * - * @param validation - * indicates whether or not validation should occur. - */ - public void setValidation(boolean validation) { - this.validating = validation; - } - - /** - * DOCUMENT ME! - * - * @return whether internal DTD declarations should be expanded into the - * DocumentType object or not. - */ - public boolean isIncludeInternalDTDDeclarations() { - return includeInternalDTDDeclarations; - } - - /** - * Sets whether internal DTD declarations should be expanded into the - * DocumentType object or not. - * - * @param include - * whether or not DTD declarations should be expanded and - * included into the DocumentType object. - */ - public void setIncludeInternalDTDDeclarations(boolean include) { - this.includeInternalDTDDeclarations = include; - } - - /** - * DOCUMENT ME! - * - * @return whether external DTD declarations should be expanded into the - * DocumentType object or not. - */ - public boolean isIncludeExternalDTDDeclarations() { - return includeExternalDTDDeclarations; - } - - /** - * Sets whether DTD external declarations should be expanded into the - * DocumentType object or not. - * - * @param include - * whether or not DTD declarations should be expanded and - * included into the DocumentType object. - */ - public void setIncludeExternalDTDDeclarations(boolean include) { - this.includeExternalDTDDeclarations = include; - } - - /** - * Sets whether String interning is enabled or disabled for element & - * attribute names and namespace URIs. This proprety is enabled by default. - * - * @return DOCUMENT ME! - */ - public boolean isStringInternEnabled() { - return stringInternEnabled; - } - - /** - * Sets whether String interning is enabled or disabled for element & - * attribute names and namespace URIs - * - * @param stringInternEnabled - * DOCUMENT ME! - */ - public void setStringInternEnabled(boolean stringInternEnabled) { - this.stringInternEnabled = stringInternEnabled; - } - - /** - * Returns whether adjacent text nodes should be merged together. - * - * @return Value of property mergeAdjacentText. - */ - public boolean isMergeAdjacentText() { - return mergeAdjacentText; - } - - /** - * Sets whether or not adjacent text nodes should be merged together when - * parsing. - * - * @param mergeAdjacentText - * New value of property mergeAdjacentText. - */ - public void setMergeAdjacentText(boolean mergeAdjacentText) { - this.mergeAdjacentText = mergeAdjacentText; - } - - /** - * Sets whether whitespace between element start and end tags should be - * ignored - * - * @return Value of property stripWhitespaceText. - */ - public boolean isStripWhitespaceText() { - return stripWhitespaceText; - } - - /** - * Sets whether whitespace between element start and end tags should be - * ignored. - * - * @param stripWhitespaceText - * New value of property stripWhitespaceText. - */ - public void setStripWhitespaceText(boolean stripWhitespaceText) { - this.stripWhitespaceText = stripWhitespaceText; - } - - /** - * Returns whether we should ignore comments or not. - * - * @return boolean - */ - public boolean isIgnoreComments() { - return ignoreComments; - } - - /** - * Sets whether we should ignore comments or not. - * - * @param ignoreComments - * whether we should ignore comments or not. - */ - public void setIgnoreComments(boolean ignoreComments) { - this.ignoreComments = ignoreComments; - } - - /** - * DOCUMENT ME! - * - * @return the DocumentFactory used to create document - * objects - */ - public DocumentFactory getDocumentFactory() { - if (factory == null) { - factory = DocumentFactory.getInstance(); - } - - return factory; - } - - /** - *

- * This sets the DocumentFactory used to create new - * documents. This method allows the building of custom DOM4J tree objects - * to be implemented easily using a custom derivation of - * {@link DocumentFactory} - *

- * - * @param documentFactory - * DocumentFactory used to create DOM4J objects - */ - public void setDocumentFactory(DocumentFactory documentFactory) { - this.factory = documentFactory; - } - - /** - * DOCUMENT ME! - * - * @return the ErrorHandler used by SAX - */ - public ErrorHandler getErrorHandler() { - return errorHandler; - } - - /** - * Sets the ErrorHandler used by the SAX - * XMLReader. - * - * @param errorHandler - * is the ErrorHandler used by SAX - */ - public void setErrorHandler(ErrorHandler errorHandler) { - this.errorHandler = errorHandler; - } - - /** - * Returns the current entity resolver used to resolve entities - * - * @return DOCUMENT ME! - */ - public EntityResolver getEntityResolver() { - return entityResolver; - } - - /** - * Sets the entity resolver used to resolve entities. - * - * @param entityResolver - * DOCUMENT ME! - */ - public void setEntityResolver(EntityResolver entityResolver) { - this.entityResolver = entityResolver; - } - - /** - * DOCUMENT ME! - * - * @return the XMLReader used to parse SAX events - * - * @throws SAXException - * DOCUMENT ME! - */ - public XMLReader getXMLReader() throws SAXException { - if (xmlReader == null) { - xmlReader = createXMLReader(); - } - - return xmlReader; - } - - /** - * Sets the XMLReader used to parse SAX events - * - * @param reader - * is the XMLReader to parse SAX events - */ - public void setXMLReader(XMLReader reader) { - this.xmlReader = reader; - } - - /** - * Returns encoding used for InputSource (null means system default - * encoding) - * - * @return encoding used for InputSource - * - */ - public String getEncoding() { - return encoding; - } - - /** - * Sets encoding used for InputSource (null means system default encoding) - * - * @param encoding - * is encoding used for InputSource - */ - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - /** - * Sets the class name of the XMLReader to be used to parse - * SAX events. - * - * @param xmlReaderClassName - * is the class name of the XMLReader to parse SAX - * events - * - * @throws SAXException - * DOCUMENT ME! - */ - public void setXMLReaderClassName(String xmlReaderClassName) - throws SAXException { - setXMLReader(XMLReaderFactory.createXMLReader(xmlReaderClassName)); - } - - /** - * Adds the ElementHandler to be called when the specified - * path is encounted. - * - * @param path - * is the path to be handled - * @param handler - * is the ElementHandler to be called by the event - * based processor. - */ - public void addHandler(String path, ElementHandler handler) { - getDispatchHandler().addHandler(path, handler); - } - - /** - * Removes the ElementHandler from the event based processor, - * for the specified path. - * - * @param path - * is the path to remove the ElementHandler for. - */ - public void removeHandler(String path) { - getDispatchHandler().removeHandler(path); - } - - /** - * When multiple ElementHandler instances have been - * registered, this will set a default ElementHandler to be - * called for any path which does NOT have a handler registered. - * - * @param handler - * is the ElementHandler to be called by the event - * based processor. - */ - public void setDefaultHandler(ElementHandler handler) { - getDispatchHandler().setDefaultHandler(handler); - } - - /** - * This method clears out all the existing handlers and default handler - * setting things back as if no handler existed. Useful when reusing an - * object instance. - */ - public void resetHandlers() { - getDispatchHandler().resetHandlers(); - } - - /** - * Returns the SAX filter being used to filter SAX events. - * - * @return the SAX filter being used or null if no SAX filter is installed - */ - public XMLFilter getXMLFilter() { - return xmlFilter; - } - - /** - * Sets the SAX filter to be used when filtering SAX events - * - * @param filter - * is the SAX filter to use or null to disable filtering - */ - public void setXMLFilter(XMLFilter filter) { - this.xmlFilter = filter; - } - - // Implementation methods - // ------------------------------------------------------------------------- - - /** - * Installs any XMLFilter objects required to allow the SAX event stream to - * be filtered and preprocessed before it gets to dom4j. - * - * @param reader - * DOCUMENT ME! - * - * @return the new XMLFilter if applicable or the original XMLReader if no - * filter is being used. - */ - protected XMLReader installXMLFilter(XMLReader reader) { - XMLFilter filter = getXMLFilter(); - - if (filter != null) { - // find the root XMLFilter - XMLFilter root = filter; - - while (true) { - XMLReader parent = root.getParent(); - - if (parent instanceof XMLFilter) { - root = (XMLFilter) parent; - } else { - break; - } - } - - root.setParent(reader); - - return filter; - } - - return reader; - } - - protected DispatchHandler getDispatchHandler() { - if (dispatchHandler == null) { - dispatchHandler = new DispatchHandler(); - } - - return dispatchHandler; - } - - protected void setDispatchHandler(DispatchHandler dispatchHandler) { - this.dispatchHandler = dispatchHandler; - } - - /** - * Factory Method to allow alternate methods of creating and configuring - * XMLReader objects - * - * @return DOCUMENT ME! - * - * @throws SAXException - * DOCUMENT ME! - */ - protected XMLReader createXMLReader() throws SAXException { - return SAXHelper.createXMLReader(isValidating()); - } - - /** - * Configures the XMLReader before use - * - * @param reader - * DOCUMENT ME! - * @param handler - * DOCUMENT ME! - * - * @throws DocumentException - * DOCUMENT ME! - */ - protected void configureReader(XMLReader reader, DefaultHandler handler) - throws DocumentException { - // configure lexical handling - SAXHelper.setParserProperty(reader, SAX_LEXICALHANDLER, handler); - - // try alternate property just in case - SAXHelper.setParserProperty(reader, SAX_LEXICAL_HANDLER, handler); - - // register the DeclHandler - if (includeInternalDTDDeclarations || includeExternalDTDDeclarations) { - SAXHelper.setParserProperty(reader, SAX_DECL_HANDLER, handler); - } - - // configure namespace support - SAXHelper.setParserFeature(reader, SAX_NAMESPACES, true); - - SAXHelper.setParserFeature(reader, SAX_NAMESPACE_PREFIXES, false); - - // string interning - SAXHelper.setParserFeature(reader, SAX_STRING_INTERNING, - isStringInternEnabled()); - - // external entites - /* - * SAXHelper.setParserFeature( reader, - * "http://xml.org/sax/properties/external-general-entities", - * includeExternalGeneralEntities ); SAXHelper.setParserFeature( reader, - * "http://xml.org/sax/properties/external-parameter-entities", - * includeExternalParameterEntities ); - */ - // use Locator2 if possible - SAXHelper.setParserFeature(reader, - "http://xml.org/sax/features/use-locator2", true); - - try { - // configure validation support - reader.setFeature("http://xml.org/sax/features/validation", - isValidating()); - - if (errorHandler != null) { - reader.setErrorHandler(errorHandler); - } else { - reader.setErrorHandler(handler); - } - } catch (Exception e) { - if (isValidating()) { - throw new DocumentException("Validation not supported for" - + " XMLReader: " + reader, e); - } - } - } - - /** - * Factory Method to allow user derived SAXContentHandler objects to be used - * - * @param reader - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - protected SAXContentHandler createContentHandler(XMLReader reader) { - return new SAXContentHandler(getDocumentFactory(), dispatchHandler); - } - - protected EntityResolver createDefaultEntityResolver(String systemId) { - String prefix = null; - - if ((systemId != null) && (systemId.length() > 0)) { - int idx = systemId.lastIndexOf('/'); - - if (idx > 0) { - prefix = systemId.substring(0, idx + 1); - } - } - - return new SAXEntityResolver(prefix); - } - - protected static class SAXEntityResolver implements EntityResolver, - Serializable { - protected String uriPrefix; - - public SAXEntityResolver(String uriPrefix) { - this.uriPrefix = uriPrefix; - } - - public InputSource resolveEntity(String publicId, String systemId) { - // try create a relative URI reader... - if ((systemId != null) && (systemId.length() > 0)) { - if ((uriPrefix != null) && (systemId.indexOf(':') <= 0)) { - systemId = uriPrefix + systemId; - } - } - - return new InputSource(systemId); - } + return new InputSource(systemId); } + } } /* * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided that the * following conditions are met: - * + * * 1. Redistributions of source code must retain copyright statements and * notices. Redistributions must also contain a copy of this document. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. The name "DOM4J" must not be used to endorse or promote products derived * from this Software without prior written permission of MetaStuff, Ltd. For * written permission, please contact dom4j-info@metastuff.com. - * + * * 4. Products derived from this Software may not be called "DOM4J" nor may * "DOM4J" appear in their names without prior written permission of MetaStuff, * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * + * * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * + * * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -1037,6 +1016,6 @@ public class SAXReader { * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXValidator.java b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXValidator.java index 11aa749ca..325ccb94e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXValidator.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXValidator.java @@ -27,7 +27,7 @@ import org.xml.sax.helpers.DefaultHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class SAXValidator { /** XMLReader used to parse the SAX events */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXWriter.java b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXWriter.java index bc5ae1027..43082c724 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/SAXWriter.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/SAXWriter.java @@ -48,7 +48,7 @@ import org.xml.sax.helpers.LocatorImpl; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.24 $ */ public class SAXWriter implements XMLReader { protected static final String[] LEXICAL_HANDLER_NAMES = { @@ -79,10 +79,10 @@ public class SAXWriter implements XMLReader { private AttributesImpl attributes = new AttributesImpl(); /** Stores the features */ - private Map features = new HashMap(); + private Map features = new HashMap(); /** Stores the properties */ - private Map properties = new HashMap(); + private Map properties = new HashMap(); /** Whether namespace declarations are exported as attributes or not */ private boolean declareNamespaceAttributes; @@ -493,9 +493,9 @@ public class SAXWriter implements XMLReader { */ public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException { - Boolean answer = (Boolean) features.get(name); + Boolean answer = features.get(name); - return (answer != null) && answer.booleanValue(); + return (answer != null) && answer; } /** @@ -535,8 +535,8 @@ public class SAXWriter implements XMLReader { * DOCUMENT ME! */ public void setProperty(String name, Object value) { - for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) { - if (LEXICAL_HANDLER_NAMES[i].equals(name)) { + for (String lexicalHandlerName : LEXICAL_HANDLER_NAMES) { + if (lexicalHandlerName.equals(name)) { setLexicalHandler((LexicalHandler) value); return; @@ -561,8 +561,8 @@ public class SAXWriter implements XMLReader { */ public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { - for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) { - if (LEXICAL_HANDLER_NAMES[i].equals(name)) { + for (String lexicalHandlerName : LEXICAL_HANDLER_NAMES) { + if (lexicalHandlerName.equals(name)) { return getLexicalHandler(); } } @@ -612,34 +612,32 @@ public class SAXWriter implements XMLReader { // ------------------------------------------------------------------------- protected void writeContent(Branch branch, NamespaceStack namespaceStack) throws SAXException { - for (Iterator iter = branch.nodeIterator(); iter.hasNext();) { - Object object = iter.next(); - - if (object instanceof Element) { - write((Element) object, namespaceStack); - } else if (object instanceof CharacterData) { - if (object instanceof Text) { - Text text = (Text) object; + for (Iterator iter = branch.nodeIterator(); iter.hasNext();) { + Node node = iter.next(); + + if (node instanceof Element) { + write((Element) node, namespaceStack); + } else if (node instanceof CharacterData) { + if (node instanceof Text) { + Text text = (Text) node; write(text.getText()); - } else if (object instanceof CDATA) { - write((CDATA) object); - } else if (object instanceof Comment) { - write((Comment) object); + } else if (node instanceof CDATA) { + write((CDATA) node); + } else if (node instanceof Comment) { + write((Comment) node); } else { throw new SAXException("Invalid Node in DOM4J content: " - + object + " of type: " + object.getClass()); + + node + " of type: " + node.getClass()); } - } else if (object instanceof String) { - write((String) object); - } else if (object instanceof Entity) { - write((Entity) object); - } else if (object instanceof ProcessingInstruction) { - write((ProcessingInstruction) object); - } else if (object instanceof Namespace) { - write((Namespace) object); + } else if (node instanceof Entity) { + write((Entity) node); + } else if (node instanceof ProcessingInstruction) { + write((ProcessingInstruction) node); + } else if (node instanceof Namespace) { + write((Namespace) node); } else { throw new SAXException("Invalid Node in DOM4J content: " - + object); + + node); } } } @@ -765,11 +763,9 @@ public class SAXWriter implements XMLReader { elementNamespace); } - List declaredNamespaces = element.declaredNamespaces(); - - for (int i = 0, size = declaredNamespaces.size(); i < size; i++) { - Namespace namespace = (Namespace) declaredNamespaces.get(i); + List declaredNamespaces = element.declaredNamespaces(); + for (Namespace namespace : declaredNamespaces) { if (!isIgnoreableNamespace(namespace, namespaceStack)) { namespaceStack.push(namespace); contentHandler.startPrefixMapping(namespace.getPrefix(), @@ -825,8 +821,8 @@ public class SAXWriter implements XMLReader { attributes.setAttributes(namespaceAttributes); } - for (Iterator iter = element.attributeIterator(); iter.hasNext();) { - Attribute attribute = (Attribute) iter.next(); + for (Iterator iter = element.attributeIterator(); iter.hasNext();) { + Attribute attribute = iter.next(); attributes.addAttribute(attribute.getNamespaceURI(), attribute .getName(), attribute.getQualifiedName(), "CDATA", attribute.getValue()); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventReader.java b/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventReader.java index 18e39b5c5..9c4f5692b 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventReader.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventReader.java @@ -293,7 +293,7 @@ public class STAXEventReader { * * @throws XMLStreamException * If an error occured reading events from the stream, or the - * stream was not positioned before a {@linkStartElement}event. + * stream was not positioned before a {@link StartElement}event. */ public Element readElement(XMLEventReader eventReader) throws XMLStreamException { @@ -348,7 +348,7 @@ public class STAXEventReader { * * @throws XMLStreamException * If an error occured reading events from the stream, or the - * stream was not positioned before an {@linkAttribute}event. + * stream was not positioned before an {@link Attribute}event. */ public org.dom4j.Attribute readAttribute(XMLEventReader reader) throws XMLStreamException { @@ -375,7 +375,7 @@ public class STAXEventReader { * * @throws XMLStreamException * If an error occured reading events from the stream, or the - * stream was not positioned before a {@linkNamespace}event. + * stream was not positioned before a {@link Namespace}event. */ public org.dom4j.Namespace readNamespace(XMLEventReader reader) throws XMLStreamException { @@ -402,7 +402,7 @@ public class STAXEventReader { * * @throws XMLStreamException * If an error occured reading events from the stream, or the - * stream was not positioned before a {@linkCharacters}event. + * stream was not positioned before a {@link Characters}event. */ public CharacterData readCharacters(XMLEventReader reader) throws XMLStreamException { @@ -429,7 +429,7 @@ public class STAXEventReader { * * @throws XMLStreamException * If an error occured reading events from the stream, or the - * stream was not positioned before a {@linkComment}event. + * stream was not positioned before a {@link Comment}event. */ public org.dom4j.Comment readComment(XMLEventReader reader) throws XMLStreamException { @@ -455,7 +455,7 @@ public class STAXEventReader { * * @throws XMLStreamException * If an error occured reading events from the stream, or the - * stream was not positioned before an {@linkEntityReference} + * stream was not positioned before an {@link EntityReference} * event. */ public Entity readEntityReference(XMLEventReader reader) @@ -518,14 +518,14 @@ public class STAXEventReader { Element elem = factory.createElement(elemName); // create attributes - for (Iterator i = startEvent.getAttributes(); i.hasNext();) { - Attribute attr = (Attribute) i.next(); + for (Iterator i = startEvent.getAttributes(); i.hasNext();) { + Attribute attr = i.next(); elem.addAttribute(createQName(attr.getName()), attr.getValue()); } // create namespaces - for (Iterator i = startEvent.getNamespaces(); i.hasNext();) { - Namespace ns = (Namespace) i.next(); + for (Iterator i = startEvent.getNamespaces(); i.hasNext();) { + Namespace ns = i.next(); elem.addNamespace(ns.getPrefix(), ns.getNamespaceURI()); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventWriter.java b/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventWriter.java index aba966298..a97dd0ca6 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventWriter.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/STAXEventWriter.java @@ -270,8 +270,8 @@ public class STAXEventWriter { QName tagName = createQName(elem.getQName()); // create attribute & namespace iterators - Iterator attrIter = new AttributeIterator(elem.attributeIterator()); - Iterator nsIter = new NamespaceIterator(elem.declaredNamespaces() + Iterator attrIter = new AttributeIterator(elem.attributeIterator()); + Iterator nsIter = new NamespaceIterator(elem.declaredNamespaces() .iterator()); // create start event @@ -288,7 +288,7 @@ public class STAXEventWriter { */ public EndElement createEndElement(Element elem) { QName tagName = createQName(elem.getQName()); - Iterator nsIter = new NamespaceIterator(elem.declaredNamespaces() + Iterator nsIter = new NamespaceIterator(elem.declaredNamespaces() .iterator()); return factory.createEndElement(tagName, nsIter); @@ -593,11 +593,11 @@ public class STAXEventWriter { * Internal {@link Iterator}implementation used to pass DOM4J {@link * Attribute}s to the stream. */ - private class AttributeIterator implements Iterator { + private class AttributeIterator implements Iterator { /** The underlying DOm4J attribute iterator. */ - private Iterator iter; + private Iterator iter; - public AttributeIterator(Iterator iter) { + public AttributeIterator(Iterator iter) { this.iter = iter; } @@ -605,8 +605,8 @@ public class STAXEventWriter { return iter.hasNext(); } - public Object next() { - Attribute attr = (Attribute) iter.next(); + public javax.xml.stream.events.Attribute next() { + Attribute attr = iter.next(); QName attrName = createQName(attr.getQName()); String value = attr.getValue(); @@ -622,10 +622,10 @@ public class STAXEventWriter { * Internal {@link Iterator}implementation used to pass DOM4J {@link * Namespace}s to the stream. */ - private class NamespaceIterator implements Iterator { - private Iterator iter; + private class NamespaceIterator implements Iterator { + private Iterator iter; - public NamespaceIterator(Iterator iter) { + public NamespaceIterator(Iterator iter) { this.iter = iter; } @@ -633,8 +633,8 @@ public class STAXEventWriter { return iter.hasNext(); } - public Object next() { - Namespace ns = (Namespace) iter.next(); + public javax.xml.stream.events.Namespace next() { + Namespace ns = iter.next(); String prefix = ns.getPrefix(); String nsURI = ns.getURI(); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/XMLResult.java b/fine-org-dom4j/src/main/java/org/dom4j/io/XMLResult.java index 5364f5883..23772e6ef 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/XMLResult.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/XMLResult.java @@ -24,7 +24,7 @@ import org.xml.sax.ext.LexicalHandler; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class XMLResult extends SAXResult { private XMLWriter xmlWriter; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/XMLWriter.java b/fine-org-dom4j/src/main/java/org/dom4j/io/XMLWriter.java index 9df68eddb..7f698edc7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/XMLWriter.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/XMLWriter.java @@ -42,6 +42,9 @@ import org.xml.sax.XMLReader; import org.xml.sax.ext.LexicalHandler; import org.xml.sax.helpers.XMLFilterImpl; +import static org.dom4j.util.StringUtils.endsWithWhitespace; +import static org.dom4j.util.StringUtils.startsWithWhitespace; + /** *

* XMLWriter takes a DOM4J tree and formats it to a stream as @@ -54,7 +57,7 @@ import org.xml.sax.helpers.XMLFilterImpl; * such as to allow suppression of the XML declaration, the encoding declaration * or whether empty documents are collapsed. *

- * + * *

* There are write(...) methods to print any of the standard * DOM4J classes, including Document and Element, @@ -63,10 +66,10 @@ import org.xml.sax.helpers.XMLFilterImpl; * preferred character encoding to be ignored. If you use encodings other than * UTF8, we recommend using the method that takes an OutputStream instead. *

- * + * * @author James Strachan * @author Joseph Bowbeer - * @version $Revision$ + * @version $Revision: 1.83 $ */ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { private static final String PAD_TEXT = " "; @@ -139,7 +142,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { private boolean inDTD; /** The namespaces used for the current element when consuming SAX events */ - private Map namespacesMap; + private Map namespacesMap; /** * what is the maximum allowed character code such as 127 in US-ASCII (7 @@ -200,7 +203,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * DOCUMENT ME! - * + * * @return true if text thats output should be escaped. This is enabled by * default. It could be disabled if the output format is textual, * like in XSLT where we can have xml, html or text output. @@ -213,7 +216,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * Sets whether text output should be escaped or not. This is enabled by * default. It could be disabled if the output format is textual, like in * XSLT where we can have xml, html or text output. - * + * * @param escapeText * DOCUMENT ME! */ @@ -225,7 +228,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * Set the initial indentation level. This can be used to output a document * (or, more likely, an element) starting at a given indent level, so it's * not always flush against the left margin. Default: 0 - * + * * @param indentLevel * the number of indents to start with */ @@ -237,7 +240,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * Returns the maximum allowed character code that should be allowed * unescaped which defaults to 127 in US-ASCII (7 bit) or 255 in ISO- (8 * bit). - * + * * @return DOCUMENT ME! */ public int getMaximumAllowedCharacter() { @@ -254,7 +257,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * escape any characters (other than the special XML characters like < * > &) If this is not explicitly set then it is defaulted from the * encoding. - * + * * @param maximumAllowedCharacter * The maximumAllowedCharacter to set */ @@ -264,7 +267,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Flushes the underlying Writer - * + * * @throws IOException * DOCUMENT ME! */ @@ -274,7 +277,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Closes the underlying Writer - * + * * @throws IOException * DOCUMENT ME! */ @@ -284,7 +287,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the new line text to the underlying Writer - * + * * @throws IOException * DOCUMENT ME! */ @@ -294,10 +297,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link Attribute}. - * + * * @param attribute * Attribute to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -313,21 +316,21 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { *

* This will print the Document to the current Writer. *

- * + * *

* Warning: using your own Writer may cause the writer's preferred character * encoding to be ignored. If you use encodings other than UTF8, we * recommend using the method that takes an OutputStream instead. *

- * + * *

* Note: as with all Writers, you may need to flush() yours after this * method returns. *

- * + * * @param doc * Document to format. - * + * * @throws IOException * if there's any problem writing. */ @@ -358,10 +361,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * s, and its value, and all its content (child nodes) to the current * Writer. *

- * + * * @param element * Element to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -375,10 +378,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link CDATA}. - * + * * @param cdata * CDATA to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -392,10 +395,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link Comment}. - * + * * @param comment * Comment to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -409,10 +412,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link DocumentType}. - * + * * @param docType * DocumentType to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -426,10 +429,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link Entity}. - * + * * @param entity * Entity to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -443,10 +446,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link Namespace}. - * + * * @param namespace * Namespace to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -460,10 +463,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link ProcessingInstruction}. - * + * * @param processingInstruction * ProcessingInstruction to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -481,10 +484,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * Print out a {@link String}, Perfoms the necessary entity escaping and * whitespace stripping. *

- * + * * @param text * is the text to output - * + * * @throws IOException * DOCUMENT ME! */ @@ -498,10 +501,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link Text}. - * + * * @param text * Text to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -515,10 +518,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given {@link Node}. - * + * * @param node * Node to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -533,10 +536,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the given object which should be a String, a Node or a List of * Nodes. - * + * * @param object * is the object to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -546,10 +549,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { } else if (object instanceof String) { write((String) object); } else if (object instanceof List) { - List list = (List) object; + List list = (List) object; - for (int i = 0, size = list.size(); i < size; i++) { - write(list.get(i)); + for (Object aList : list) { + write(aList); } } else if (object != null) { throw new IOException("Invalid object: " + object); @@ -561,16 +564,17 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * Writes the opening tag of an {@link Element}, including its {@link * Attribute}s but without its content. *

- * + * * @param element * Element to output. - * + * * @throws IOException * DOCUMENT ME! */ public void writeOpen(Element element) throws IOException { writer.write("<"); writer.write(element.getQualifiedName()); + writeNamespaces(element); writeAttributes(element); writer.write(">"); } @@ -579,10 +583,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { *

* Writes the closing tag of an {@link Element} *

- * + * * @param element * Element to output. - * + * * @throws IOException * DOCUMENT ME! */ @@ -599,8 +603,8 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException { - for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) { - if (LEXICAL_HANDLER_NAMES[i].equals(name)) { + for (String lexicalHandlerName : LEXICAL_HANDLER_NAMES) { + if (lexicalHandlerName.equals(name)) { setLexicalHandler((LexicalHandler) value); return; @@ -612,8 +616,8 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { - for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) { - if (LEXICAL_HANDLER_NAMES[i].equals(name)) { + for (String lexicalHandlerName : LEXICAL_HANDLER_NAMES) { + if (lexicalHandlerName.equals(name)) { return getLexicalHandler(); } } @@ -662,7 +666,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { public void startPrefixMapping(String prefix, String uri) throws SAXException { if (namespacesMap == null) { - namespacesMap = new HashMap(); + namespacesMap = new HashMap(); } namespacesMap.put(prefix, uri); @@ -975,10 +979,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Determines if element is a special case of XML elements where it contains * an xml:space attribute of "preserve". If it does, then retain whitespace. - * + * * @param element * DOCUMENT ME! - * + * * @return DOCUMENT ME! */ protected final boolean isElementSpacePreserved(Element element) { @@ -986,12 +990,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { boolean preserveFound = preserve; // default to global state if (attr != null) { - if ("xml".equals(attr.getNamespacePrefix()) - && "preserve".equals(attr.getText())) { - preserveFound = true; - } else { - preserveFound = false; - } + preserveFound = "xml".equals(attr.getNamespacePrefix()) && "preserve".equals(attr.getText()); } return preserveFound; @@ -1003,10 +1002,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * whitespace trimming occurs to avoid problems with multiple text nodes * being created due to text content that spans parser buffers in a SAX * parser. - * + * * @param element * DOCUMENT ME! - * + * * @throws IOException * DOCUMENT ME! */ @@ -1023,34 +1022,34 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { // concatenate adjacent text nodes together // so that whitespace trimming works properly Text lastTextNode = null; - StringBuffer buff = null; + StringBuilder buff = null; boolean textOnly = true; - for (int i = 0, size = element.nodeCount(); i < size; i++) { - Node node = element.node(i); - + for (Node node : element.content()) { if (node instanceof Text) { if (lastTextNode == null) { lastTextNode = (Text) node; } else { if (buff == null) { - buff = new StringBuffer(lastTextNode.getText()); + buff = new StringBuilder(lastTextNode.getText()); } - buff.append(((Text) node).getText()); + buff.append((node).getText()); } } else { if (!textOnly && format.isPadText()) { // only add the PAD_TEXT if the text itself starts with // whitespace - char firstChar = 'a'; + final boolean startsWithWhitespace; if (buff != null) { - firstChar = buff.charAt(0); + startsWithWhitespace = startsWithWhitespace(buff); } else if (lastTextNode != null) { - firstChar = lastTextNode.getText().charAt(0); + startsWithWhitespace = startsWithWhitespace(lastTextNode.getText()); + } else { + startsWithWhitespace = false; } - if (Character.isWhitespace(firstChar)) { + if (startsWithWhitespace) { writer.write(PAD_TEXT); } } @@ -1066,15 +1065,14 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { if (format.isPadText()) { // only add the PAD_TEXT if the text itself ends // with whitespace - char lastTextChar = 'a'; + final boolean endsWithWhitespace; if (buff != null) { - lastTextChar = buff.charAt(buff.length() - 1); - } else if (lastTextNode != null) { - String txt = lastTextNode.getText(); - lastTextChar = txt.charAt(txt.length() - 1); + endsWithWhitespace = endsWithWhitespace(buff); + } else { + endsWithWhitespace = endsWithWhitespace(lastTextNode.getText()); } - if (Character.isWhitespace(lastTextChar)) { + if (endsWithWhitespace) { writer.write(PAD_TEXT); } } @@ -1091,14 +1089,14 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { if (!textOnly && format.isPadText()) { // only add the PAD_TEXT if the text itself starts with // whitespace - char firstChar = 'a'; + final boolean startsWithWhitespace; if (buff != null) { - firstChar = buff.charAt(0); + startsWithWhitespace = startsWithWhitespace(buff); } else { - firstChar = lastTextNode.getText().charAt(0); + startsWithWhitespace = startsWithWhitespace(lastTextNode.getText()); } - if (Character.isWhitespace(firstChar)) { + if (startsWithWhitespace) { writer.write(PAD_TEXT); } } @@ -1115,9 +1113,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { } else { Node lastTextNode = null; - for (int i = 0, size = element.nodeCount(); i < size; i++) { - Node node = element.node(i); - + for (Node node : element.content()) { if (node instanceof Text) { writeNode(node); lastTextNode = node; @@ -1125,10 +1121,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { if ((lastTextNode != null) && format.isPadText()) { // only add the PAD_TEXT if the text itself ends with // whitespace - String txt = lastTextNode.getText(); - char lastTextChar = txt.charAt(txt.length() - 1); - - if (Character.isWhitespace(lastTextChar)) { + if (endsWithWhitespace(lastTextNode.getText())) { writer.write(PAD_TEXT); } } @@ -1174,17 +1167,15 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the SAX namepsaces - * + * * @throws IOException * DOCUMENT ME! */ protected void writeNamespaces() throws IOException { if (namespacesMap != null) { - for (Iterator iter = namespacesMap.entrySet().iterator(); iter - .hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); - String prefix = (String) entry.getKey(); - String uri = (String) entry.getValue(); + for (Map.Entry entry : namespacesMap.entrySet()) { + String prefix = entry.getKey(); + String uri = entry.getValue(); writeNamespace(prefix, uri); } @@ -1194,15 +1185,15 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the SAX namepsaces - * + * * @param prefix * the prefix * @param uri * the namespace uri - * - * @throws IOException + * + * @throws IOException DOCUMENT ME! */ - protected void writeNamespace(String prefix, String uri) + protected void writeNamespace(String prefix, String uri) throws IOException { if ((prefix != null) && (prefix.length() > 0)) { writer.write(" xmlns:"); @@ -1216,6 +1207,19 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { writer.write("\""); } + /** + * Writes all namespaces declared directly on element. + * + * @throws IOException + */ + protected void writeNamespaces(Element element) throws IOException { + assert element != null; + for (Namespace ns : element.declaredNamespaces()) { + writeNamespace(ns); + namespaceStack.push(ns); + } + } + protected void writeProcessingInstruction(ProcessingInstruction pi) throws IOException { // indent(); @@ -1259,12 +1263,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { writer.write(token); lastOutputNodeType = Node.TEXT_NODE; - lastChar = token.charAt(token.length() - 1); } } else { lastOutputNodeType = Node.TEXT_NODE; writer.write(text); - lastChar = text.charAt(text.length() - 1); } } } @@ -1272,10 +1274,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * This method is used to write out Nodes that contain text and still allow * for xml:space to be handled properly. - * + * * @param node * DOCUMENT ME! - * + * * @throws IOException * DOCUMENT ME! */ @@ -1289,7 +1291,6 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { lastOutputNodeType = Node.TEXT_NODE; writer.write(text); - lastChar = text.charAt(text.length() - 1); } } @@ -1362,9 +1363,9 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { } // try to register for lexical events - for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) { + for (String lexicalHandlerName : LEXICAL_HANDLER_NAMES) { try { - parent.setProperty(LEXICAL_HANDLER_NAMES[i], this); + parent.setProperty(lexicalHandlerName, this); break; } catch (SAXNotRecognizedException ex) { @@ -1434,10 +1435,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Writes the attributes of the given element - * + * * @param element * DOCUMENT ME! - * + * * @throws IOException * DOCUMENT ME! */ @@ -1481,26 +1482,24 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { writeNamespace(null, uri); } } else { - char quote = format.getAttributeQuoteCharacter(); - writer.write(" "); - writer.write(attribute.getQualifiedName()); - writer.write("="); - writer.write(quote); - writeEscapeAttributeEntities(attribute.getValue()); - writer.write(quote); + writeAttribute(attribute); } } } protected void writeAttribute(Attribute attribute) throws IOException { + writeAttribute(attribute.getQualifiedName(), attribute.getValue()); + } + + protected void writeAttribute(String qualifiedName, String value) throws IOException { writer.write(" "); - writer.write(attribute.getQualifiedName()); + writer.write(qualifiedName); writer.write("="); char quote = format.getAttributeQuoteCharacter(); writer.write(quote); - writeEscapeAttributeEntities(attribute.getValue()); + writeEscapeAttributeEntities(value); writer.write(quote); lastOutputNodeType = Node.ATTRIBUTE_NODE; @@ -1514,13 +1513,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { protected void writeAttribute(Attributes attributes, int index) throws IOException { - char quote = format.getAttributeQuoteCharacter(); - writer.write(" "); - writer.write(attributes.getQName(index)); - writer.write("="); - writer.write(quote); - writeEscapeAttributeEntities(attributes.getValue(index)); - writer.write(quote); + writeAttribute(attributes.getQName(index), attributes.getValue(index)); } protected void indent() throws IOException { @@ -1537,29 +1530,26 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { *

* This will print a new line only if the newlines flag was set to true *

- * + * * @throws IOException * DOCUMENT ME! */ protected void writePrintln() throws IOException { if (format.isNewlines()) { - String seperator = format.getLineSeparator(); - if (lastChar != seperator.charAt(seperator.length() - 1)) { - writer.write(format.getLineSeparator()); - } + writer.write(format.getLineSeparator()); } } /** * Get an OutputStreamWriter, use preferred encoding. - * + * * @param outStream * DOCUMENT ME! * @param encoding * DOCUMENT ME! - * + * * @return DOCUMENT ME! - * + * * @throws UnsupportedEncodingException * DOCUMENT ME! */ @@ -1573,7 +1563,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * This will write the declaration to the given Writer. Assumes XML version * 1.0 since we don't directly know. *

- * + * * @throws IOException * DOCUMENT ME! */ @@ -1633,10 +1623,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * This will take the pre-defined entities in XML 1.0 and convert their * character representation to the appropriate entity reference, suitable * for XML attributes. - * + * * @param text * DOCUMENT ME! - * + * * @return DOCUMENT ME! */ protected String escapeElementEntities(String text) { @@ -1647,44 +1637,37 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { for (i = 0; i < size; i++) { String entity = null; - char c = text.charAt(i); + int c = text.codePointAt(i); switch (c) { case '<': entity = "<"; - break; - case '>': entity = ">"; - break; - case '&': entity = "&"; - break; - case '\t': case '\n': case '\r': - // don't encode standard whitespace characters if (preserve) { - entity = String.valueOf(c); + entity = String.valueOf((char) c); } - break; default: if ((c < 32) || shouldEncodeChar(c)) { - entity = "&#" + (int) c + ";"; + entity = "&#" + c + ";"; } break; } + if (entity != null) { if (block == null) { block = text.toCharArray(); @@ -1693,6 +1676,12 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { buffer.append(block, last, i - last); buffer.append(entity); last = i + 1; + if (Character.isSupplementaryCodePoint(c)) { + last++; + } + } + if (Character.isSupplementaryCodePoint(c)) { + i++; } } @@ -1725,10 +1714,10 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * This will take the pre-defined entities in XML 1.0 and convert their * character representation to the appropriate entity reference, suitable * for XML attributes. - * + * * @param text * DOCUMENT ME! - * + * * @return DOCUMENT ME! */ protected String escapeAttributeEntities(String text) { @@ -1741,53 +1730,37 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { for (i = 0; i < size; i++) { String entity = null; - char c = text.charAt(i); + int c = text.codePointAt(i); switch (c) { case '<': entity = "<"; - break; - case '>': entity = ">"; - break; - case '\'': - if (quote == '\'') { entity = "'"; } - break; - case '\"': - if (quote == '\"') { entity = """; } - break; - case '&': entity = "&"; - break; - case '\t': case '\n': case '\r': - // don't encode standard whitespace characters break; - default: - if ((c < 32) || shouldEncodeChar(c)) { - entity = "&#" + (int) c + ";"; + entity = "&#" + c + ";"; } - break; } @@ -1799,6 +1772,12 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { buffer.append(block, last, i - last); buffer.append(entity); last = i + 1; + if(Character.isSupplementaryCodePoint(c)) { + last++; + } + } + if(Character.isSupplementaryCodePoint(c)) { + i++; } } @@ -1823,23 +1802,23 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { /** * Should the given character be escaped. This depends on the encoding of * the document. - * - * @param c + * + * @param codepoint Unicode codepoint. * DOCUMENT ME! - * + * * @return boolean */ - protected boolean shouldEncodeChar(char c) { + protected boolean shouldEncodeChar(int codepoint) { int max = getMaximumAllowedCharacter(); - return (max > 0) && (c > max); + return (max > 0) && (codepoint > max); } /** * Returns the maximum allowed character code that should be allowed * unescaped which defaults to 127 in US-ASCII (7 bit) or 255 in ISO- (8 * bit). - * + * * @return DOCUMENT ME! */ protected int defaultMaximumAllowedCharacter() { @@ -1880,7 +1859,7 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * setTrimText, setNewLines, etc. Put in to support the HTMLWriter, in the * way that it pushes the current newline/trim state onto a stack and * overrides the state within preformatted tags. - * + * * @return DOCUMENT ME! */ protected OutputFormat getOutputFormat() { @@ -1900,24 +1879,24 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided that the * following conditions are met: - * + * * 1. Redistributions of source code must retain copyright statements and * notices. Redistributions must also contain a copy of this document. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. The name "DOM4J" must not be used to endorse or promote products derived * from this Software without prior written permission of MetaStuff, Ltd. For * written permission, please contact dom4j-info@metastuff.com. - * + * * 4. Products derived from this Software may not be called "DOM4J" nor may * "DOM4J" appear in their names without prior written permission of MetaStuff, * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * + * * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * + * * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -1929,6 +1908,6 @@ public class XMLWriter extends XMLFilterImpl implements LexicalHandler { * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/XPP3Reader.java b/fine-org-dom4j/src/main/java/org/dom4j/io/XPP3Reader.java index b5228cb5d..6cd393dd7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/XPP3Reader.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/XPP3Reader.java @@ -37,7 +37,7 @@ import org.xmlpull.v1.XmlPullParserFactory; * * @author Pelle Braendgaard * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.3 $ */ public class XPP3Reader { /** DocumentFactory used to create new document objects */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/XPPReader.java b/fine-org-dom4j/src/main/java/org/dom4j/io/XPPReader.java index d4d2e82d2..4b7529fde 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/XPPReader.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/XPPReader.java @@ -37,7 +37,7 @@ import org.gjt.xpp.XmlPullParserFactory; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class XPPReader { /** DocumentFactory used to create new document objects */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/io/package-info.java new file mode 100644 index 000000000..0f2f0e9d9 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/io/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides input and output via SAX and DOM together with writing dom4j objects to streams as XML text. + */ +package org.dom4j.io; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/io/package.html b/fine-org-dom4j/src/main/java/org/dom4j/io/package.html deleted file mode 100644 index fe02b3a4d..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/io/package.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -

Provides input and output via SAX and DOM together with writing dom4j - objects to streams as XML text.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBModifier.java b/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBModifier.java index 8a410d107..acbaed5f7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBModifier.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBModifier.java @@ -51,7 +51,7 @@ public class JAXBModifier extends JAXBSupport { private OutputFormat outputFormat; - private HashMap modifiers = new HashMap(); + private HashMap modifiers = new HashMap(); /** * Creates a new JAXBModifier for the given JAXB context path. This is the @@ -105,7 +105,7 @@ public class JAXBModifier extends JAXBSupport { /** * Creates a new JAXBModifier for the given JAXB context path, using the - * specified {@link java.lang.Classloader}. The specified {@link + * specified {@link java.lang.ClassLoader}. The specified {@link * org.dom4j.io.OutputFormat} will be used while writing the XML stream. * * @param contextPath @@ -441,13 +441,13 @@ public class JAXBModifier extends JAXBSupport { modifier.resetModifiers(); - Iterator modifierIt = modifiers.entrySet().iterator(); + Iterator> modifierIt = modifiers.entrySet().iterator(); while (modifierIt.hasNext()) { - Map.Entry entry = (Map.Entry) modifierIt.next(); + Map.Entry entry = modifierIt.next(); ElementModifier mod = new JAXBElementModifier(this, - (JAXBObjectModifier) entry.getValue()); - getModifier().addModifier((String) entry.getKey(), mod); + entry.getValue()); + getModifier().addModifier(entry.getKey(), mod); } modifier.setXMLWriter(getXMLWriter()); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBReader.java b/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBReader.java index f35645949..3f5283747 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBReader.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBReader.java @@ -28,7 +28,7 @@ import org.xml.sax.InputSource; /** * Reads an XML document and creates a DOM4J tree from SAX parsing events. * {@link JAXBObjectHandler}objects can be registered to automatically receive - * unmarshalled XML fragments. Registered {@linkorg.dom4j.ElementHandler} + * unmarshalled XML fragments. Registered {@link org.dom4j.ElementHandler} * implementations are notified when a certain element path is encountered * * @author Wonne Keysers (Realsoftware.be) @@ -57,7 +57,7 @@ public class JAXBReader extends JAXBSupport { /** * Creates a new JAXBReader for the given JAXB context path, using the - * specified {@link java.lang.Classloader}. This is the Java package where + * specified {@link java.lang.ClassLoader}. This is the Java package where * JAXB can find the generated XML classes. This package MUST contain * jaxb.properties! * @@ -333,7 +333,7 @@ public class JAXBReader extends JAXBSupport { * Set to true when DOM4J elements must immediately be pruned from the tree. * The {@link Document}will not be available afterwards! * - * @param pruneElements + * @param pruneElements DOCUMENT ME! */ public void setPruneElements(boolean pruneElements) { this.pruneElements = pruneElements; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBWriter.java b/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBWriter.java index b713d70ae..191d71357 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBWriter.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/jaxb/JAXBWriter.java @@ -70,7 +70,7 @@ public class JAXBWriter extends JAXBSupport { /** * Creates a new JAXBWriter for the given JAXB context path, using the - * specified {@link java.lang.Classloader}. (This is the Java package where + * specified {@link java.lang.ClassLoader}. (This is the Java package where * JAXB can find the generated XML classes. This package MUST contain * jaxb.properties!) * @@ -87,7 +87,7 @@ public class JAXBWriter extends JAXBSupport { /** * Creates a new JAXBWriter for the given JAXB context path, using the - * specified {@link java.lang.Classloader}. The specied {@link + * specified {@link java.lang.ClassLoader}. The specied {@link * org.dom4j.io.OutputFormat} will be used while writing the XML stream. * * @param contextPath @@ -148,7 +148,7 @@ public class JAXBWriter extends JAXBSupport { * @param writer * writer to write to * - * @throws IOException + * @throws IOException DOCUMENT ME! */ public void setOutput(Writer writer) throws IOException { getWriter().setWriter(writer); @@ -185,7 +185,7 @@ public class JAXBWriter extends JAXBSupport { * {@link javax.xml.bind.Element}instances can be created using the * ObjectFactory that is generated by the JAXB compiler. * - * @param jaxbObject + * @param jaxbObject DOCUMENT ME! * * @throws IOException * if an error occured while writing the output diff --git a/fine-org-dom4j/src/main/java/org/dom4j/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/package-info.java new file mode 100644 index 000000000..d4903687b --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/package-info.java @@ -0,0 +1,4 @@ +/** + * Defines the XML Document Object Model in Java interfaces together with some helper classes. + */ +package org.dom4j; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/package.html b/fine-org-dom4j/src/main/java/org/dom4j/package.html deleted file mode 100644 index a1b8a9d3e..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/package.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -

Defines the XML Document Object Model in Java interfaces together - with some helper classes.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/Action.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/Action.java index a10ad9a9b..8f287f9d3 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/Action.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/Action.java @@ -16,7 +16,7 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public interface Action { void run(Node node) throws Exception; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/Mode.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/Mode.java index 26e910de8..2293aaa04 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/Mode.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/Mode.java @@ -24,16 +24,16 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class Mode { private RuleSet[] ruleSets = new RuleSet[Pattern.NUMBER_OF_TYPES]; /** Map of exact (local) element names to RuleSet instances */ - private Map elementNameRuleSets; + private Map elementNameRuleSets; /** Map of exact (local) attribute names to RuleSet instances */ - private Map attributeNameRuleSets; + private Map attributeNameRuleSets; public Mode() { } @@ -240,12 +240,12 @@ public class Mode { * * @return the Map (which will be created if the given map was null */ - protected Map addToNameMap(Map map, String name, Rule rule) { + protected Map addToNameMap(Map map, String name, Rule rule) { if (map == null) { - map = new HashMap(); + map = new HashMap(); } - RuleSet ruleSet = (RuleSet) map.get(name); + RuleSet ruleSet = map.get(name); if (ruleSet == null) { ruleSet = new RuleSet(); @@ -257,9 +257,9 @@ public class Mode { return map; } - protected void removeFromNameMap(Map map, String name, Rule rule) { + protected void removeFromNameMap(Map map, String name, Rule rule) { if (map != null) { - RuleSet ruleSet = (RuleSet) map.get(name); + RuleSet ruleSet = map.get(name); if (ruleSet != null) { ruleSet.removeRule(rule); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/NullAction.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/NullAction.java index 93b9ff144..b506df3e5 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/NullAction.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/NullAction.java @@ -15,7 +15,7 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class NullAction implements Action { /** Singleton instance */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/Pattern.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/Pattern.java index 819fcb61b..13583053a 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/Pattern.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/Pattern.java @@ -17,7 +17,7 @@ import org.dom4j.NodeFilter; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.6 $ */ public interface Pattern extends NodeFilter { // These node numbers are compatable with DOM4J's Node types diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/Rule.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/Rule.java index b3d60e926..a88e369f5 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/Rule.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/Rule.java @@ -14,283 +14,280 @@ import org.dom4j.Node; * Rule matches against DOM4J Node so that some action can be * performed such as in the XSLT processing model. *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ -public class Rule implements Comparable { - /** Holds value of property mode. */ - private String mode; - - /** Holds value of property importPrecedence. */ - private int importPrecedence; - - /** Holds value of property priority. */ - private double priority; - - /** Holds value of property appearenceCount. */ - private int appearenceCount; - - /** Holds value of property pattern. */ - private Pattern pattern; - - /** Holds value of property action. */ - private Action action; - - public Rule() { - this.priority = Pattern.DEFAULT_PRIORITY; - } - - public Rule(Pattern pattern) { - this.pattern = pattern; - this.priority = pattern.getPriority(); - } - - public Rule(Pattern pattern, Action action) { - this(pattern); - this.action = action; - } - - /** - * Constructs a new Rule with the same instance data as the given rule but a - * different pattern. - * - * @param that - * DOCUMENT ME! - * @param pattern - * DOCUMENT ME! - */ - public Rule(Rule that, Pattern pattern) { - this.mode = that.mode; - this.importPrecedence = that.importPrecedence; - this.priority = that.priority; - this.appearenceCount = that.appearenceCount; - this.action = that.action; - this.pattern = pattern; - } - - public boolean equals(Object that) { - if (that instanceof Rule) { - return compareTo((Rule) that) == 0; - } - - return false; - } - - public int hashCode() { - return importPrecedence + appearenceCount; - } - - public int compareTo(Object that) { - if (that instanceof Rule) { - return compareTo((Rule) that); - } - - return getClass().getName().compareTo(that.getClass().getName()); - } - - /** - * Compares two rules in XSLT processing model order assuming that the modes - * are equal. - * - * @param that - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public int compareTo(Rule that) { - int answer = this.importPrecedence - that.importPrecedence; - - if (answer == 0) { - answer = (int) Math.round(this.priority - that.priority); - - if (answer == 0) { - answer = this.appearenceCount - that.appearenceCount; - } - } - - return answer; - } - - public String toString() { - return super.toString() + "[ pattern: " + getPattern() + " action: " - + getAction() + " ]"; - } - - /** - * DOCUMENT ME! - * - * @param node - * DOCUMENT ME! - * - * @return true if the pattern matches the given DOM4J node. - */ - public final boolean matches(Node node) { - return pattern.matches(node); - } - - /** - * If this rule contains a union pattern then this method should return an - * array of Rules which describe the union rule, which should contain more - * than one rule. Otherwise this method should return null. - * - * @return an array of the rules which make up this union rule or null if - * this rule is not a union rule - */ - public Rule[] getUnionRules() { - Pattern[] patterns = pattern.getUnionPatterns(); - - if (patterns == null) { - return null; - } - - int size = patterns.length; - Rule[] answer = new Rule[size]; - - for (int i = 0; i < size; i++) { - answer[i] = new Rule(this, patterns[i]); - } - - return answer; - } - - /** - * DOCUMENT ME! - * - * @return the type of node the pattern matches which by default should - * return ANY_NODE if it can match any kind of node. - */ - public final short getMatchType() { - return pattern.getMatchType(); - } - - /** - * For patterns which only match an ATTRIBUTE_NODE or an ELEMENT_NODE then - * this pattern may return the name of the element or attribute it matches. - * This allows a more efficient rule matching algorithm to be performed, - * rather than a brute force approach of evaluating every pattern for a - * given Node. - * - * @return the name of the element or attribute this pattern matches or null - * if this pattern matches any or more than one name. - */ - public final String getMatchesNodeName() { - return pattern.getMatchesNodeName(); - } - - /** - * Getter for property mode. - * - * @return Value of property mode. - */ - public String getMode() { - return mode; - } - - /** - * Setter for property mode. - * - * @param mode - * New value of property mode. - */ - public void setMode(String mode) { - this.mode = mode; - } - - /** - * Getter for property importPrecedence. - * - * @return Value of property importPrecedence. - */ - public int getImportPrecedence() { - return importPrecedence; - } - - /** - * Setter for property importPrecedence. - * - * @param importPrecedence - * New value of property importPrecedence. - */ - public void setImportPrecedence(int importPrecedence) { - this.importPrecedence = importPrecedence; - } - - /** - * Getter for property priority. - * - * @return Value of property priority. - */ - public double getPriority() { - return priority; - } - - /** - * Setter for property priority. - * - * @param priority - * New value of property priority. - */ - public void setPriority(double priority) { - this.priority = priority; - } - - /** - * Getter for property appearenceCount. - * - * @return Value of property appearenceCount. - */ - public int getAppearenceCount() { - return appearenceCount; - } - - /** - * Setter for property appearenceCount. - * - * @param appearenceCount - * New value of property appearenceCount. - */ - public void setAppearenceCount(int appearenceCount) { - this.appearenceCount = appearenceCount; - } - - /** - * Getter for property pattern. - * - * @return Value of property pattern. - */ - public Pattern getPattern() { - return pattern; - } - - /** - * Setter for property pattern. - * - * @param pattern - * New value of property pattern. - */ - public void setPattern(Pattern pattern) { - this.pattern = pattern; - } - - /** - * Getter for property action. - * - * @return Value of property action. - */ - public Action getAction() { - return action; - } - - /** - * Setter for property action. - * - * @param action - * New value of property action. - */ - public void setAction(Action action) { - this.action = action; - } +public class Rule implements Comparable { + /** + * Holds value of property mode. + */ + private String mode; + + /** + * Holds value of property importPrecedence. + */ + private int importPrecedence; + + /** + * Holds value of property priority. + */ + private double priority; + + /** + * Holds value of property appearenceCount. + */ + private int appearenceCount; + + /** + * Holds value of property pattern. + */ + private Pattern pattern; + + /** + * Holds value of property action. + */ + private Action action; + + public Rule() { + this.priority = Pattern.DEFAULT_PRIORITY; + } + + public Rule(Pattern pattern) { + this.pattern = pattern; + this.priority = pattern.getPriority(); + } + + public Rule(Pattern pattern, Action action) { + this(pattern); + this.action = action; + } + + /** + * Constructs a new Rule with the same instance data as the given rule but a + * different pattern. + * + * @param that DOCUMENT ME! + * @param pattern DOCUMENT ME! + */ + public Rule(Rule that, Pattern pattern) { + this.mode = that.mode; + this.importPrecedence = that.importPrecedence; + this.priority = that.priority; + this.appearenceCount = that.appearenceCount; + this.action = that.action; + this.pattern = pattern; + } + + public boolean equals(Object that) { + if (that instanceof Rule) { + return compareTo((Rule) that) == 0; + } + + return false; + } + + public int hashCode() { + return importPrecedence + appearenceCount; + } + + /** + * Compares two rules in XSLT processing model order assuming that the modes + * are equal. + * + * @param that DOCUMENT ME! + * @return DOCUMENT ME! + */ + public int compareTo(Rule that) { + int answer = compareInt(this.importPrecedence, that.importPrecedence); + + if (answer == 0) { + answer = Double.compare(this.priority, that.priority); + + if (answer == 0) { + answer = compareInt(this.appearenceCount, that.appearenceCount); + } + } + + return answer; + } + + public String toString() { + return super.toString() + "[ pattern: " + getPattern() + " action: " + + getAction() + " ]"; + } + + /** + * DOCUMENT ME! + * + * @param node DOCUMENT ME! + * @return true if the pattern matches the given DOM4J node. + */ + public final boolean matches(Node node) { + return pattern.matches(node); + } + + /** + * If this rule contains a union pattern then this method should return an + * array of Rules which describe the union rule, which should contain more + * than one rule. Otherwise this method should return null. + * + * @return an array of the rules which make up this union rule or null if + * this rule is not a union rule + */ + public Rule[] getUnionRules() { + Pattern[] patterns = pattern.getUnionPatterns(); + + if (patterns == null) { + return null; + } + + int size = patterns.length; + Rule[] answer = new Rule[size]; + + for (int i = 0; i < size; i++) { + answer[i] = new Rule(this, patterns[i]); + } + + return answer; + } + + /** + * DOCUMENT ME! + * + * @return the type of node the pattern matches which by default should + * return ANY_NODE if it can match any kind of node. + */ + public final short getMatchType() { + return pattern.getMatchType(); + } + + /** + * For patterns which only match an ATTRIBUTE_NODE or an ELEMENT_NODE then + * this pattern may return the name of the element or attribute it matches. + * This allows a more efficient rule matching algorithm to be performed, + * rather than a brute force approach of evaluating every pattern for a + * given Node. + * + * @return the name of the element or attribute this pattern matches or null + * if this pattern matches any or more than one name. + */ + public final String getMatchesNodeName() { + return pattern.getMatchesNodeName(); + } + + /** + * Getter for property mode. + * + * @return Value of property mode. + */ + public String getMode() { + return mode; + } + + /** + * Setter for property mode. + * + * @param mode New value of property mode. + */ + public void setMode(String mode) { + this.mode = mode; + } + + /** + * Getter for property importPrecedence. + * + * @return Value of property importPrecedence. + */ + public int getImportPrecedence() { + return importPrecedence; + } + + /** + * Setter for property importPrecedence. + * + * @param importPrecedence New value of property importPrecedence. + */ + public void setImportPrecedence(int importPrecedence) { + this.importPrecedence = importPrecedence; + } + + /** + * Getter for property priority. + * + * @return Value of property priority. + */ + public double getPriority() { + return priority; + } + + /** + * Setter for property priority. + * + * @param priority New value of property priority. + */ + public void setPriority(double priority) { + this.priority = priority; + } + + /** + * Getter for property appearenceCount. + * + * @return Value of property appearenceCount. + */ + public int getAppearenceCount() { + return appearenceCount; + } + + /** + * Setter for property appearenceCount. + * + * @param appearenceCount New value of property appearenceCount. + */ + public void setAppearenceCount(int appearenceCount) { + this.appearenceCount = appearenceCount; + } + + /** + * Getter for property pattern. + * + * @return Value of property pattern. + */ + public Pattern getPattern() { + return pattern; + } + + /** + * Setter for property pattern. + * + * @param pattern New value of property pattern. + */ + public void setPattern(Pattern pattern) { + this.pattern = pattern; + } + + /** + * Getter for property action. + * + * @return Value of property action. + */ + public Action getAction() { + return action; + } + + /** + * Setter for property action. + * + * @param action New value of property action. + */ + public void setAction(Action action) { + this.action = action; + } + + private static int compareInt(int value1, int value2) { + //return Integer.compare(value1, value2); + return (value1 < value2) ? -1 : ((value1 == value2) ? 0 : 1); + } } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleManager.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleManager.java index 72fcd8c61..c84613958 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleManager.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleManager.java @@ -21,11 +21,11 @@ import org.dom4j.rule.pattern.NodeTypePattern; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class RuleManager { /** Map of modes indexed by mode */ - private HashMap modes = new HashMap(); + private HashMap modes = new HashMap(); /** * A counter so that rules can be ordered by the order in which they were @@ -49,7 +49,7 @@ public class RuleManager { * then it will be created. */ public Mode getMode(String modeName) { - Mode mode = (Mode) modes.get(modeName); + Mode mode = modes.get(modeName); if (mode == null) { mode = createMode(); @@ -66,8 +66,8 @@ public class RuleManager { Rule[] childRules = rule.getUnionRules(); if (childRules != null) { - for (int i = 0, size = childRules.length; i < size; i++) { - mode.addRule(childRules[i]); + for (Rule childRule : childRules) { + mode.addRule(childRule); } } else { mode.addRule(rule); @@ -79,8 +79,8 @@ public class RuleManager { Rule[] childRules = rule.getUnionRules(); if (childRules != null) { - for (int i = 0, size = childRules.length; i < size; i++) { - mode.removeRule(childRules[i]); + for (Rule childRule : childRules) { + mode.removeRule(childRule); } } else { mode.removeRule(rule); @@ -99,7 +99,7 @@ public class RuleManager { * @return the matching Rule or no rule if none matched */ public Rule getMatchingRule(String modeName, Node node) { - Mode mode = (Mode) modes.get(modeName); + Mode mode = modes.get(modeName); if (mode != null) { return mode.getMatchingRule(node); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleSet.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleSet.java index 506a0dba0..37f48981f 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleSet.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/RuleSet.java @@ -21,11 +21,11 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class RuleSet { /** An unordered list of Rule objects */ - private ArrayList rules = new ArrayList(); + private ArrayList rules = new ArrayList(); /** A lazily evaluated and cached array of rules sorted */ private Rule[] ruleArray; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/Stylesheet.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/Stylesheet.java index 9d5585544..59b4b53e9 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/Stylesheet.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/Stylesheet.java @@ -7,13 +7,9 @@ package org.dom4j.rule; -import java.util.Iterator; import java.util.List; -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.Node; -import org.dom4j.XPath; +import org.dom4j.*; /** *

@@ -23,7 +19,7 @@ import org.dom4j.XPath; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.14 $ */ public class Stylesheet { private RuleManager ruleManager = new RuleManager(); @@ -57,39 +53,13 @@ public class Stylesheet { ruleManager.removeRule(rule); } - /** - * Runs this stylesheet on the given input which should be either a Node or - * a List of Node objects. - * - * @param input - * the input to run this stylesheet on - * - * @throws Exception - * if something goes wrong - */ - public void run(Object input) throws Exception { - run(input, this.modeName); - } - - public void run(Object input, String mode) throws Exception { - if (input instanceof Node) { - run((Node) input, mode); - } else if (input instanceof List) { - run((List) input, mode); - } - } - - public void run(List list) throws Exception { + public void run(List list) throws Exception { run(list, this.modeName); } - public void run(List list, String mode) throws Exception { - for (int i = 0, size = list.size(); i < size; i++) { - Object object = list.get(i); - - if (object instanceof Node) { - run((Node) object, mode); - } + public void run(List list, String mode) throws Exception { + for (Node node : list) { + run(node, mode); } } @@ -134,56 +104,52 @@ public class Stylesheet { throws Exception { Mode mod = ruleManager.getMode(mode); - List list = xpath.selectNodes(input); - Iterator it = list.iterator(); - while (it.hasNext()) { - Node current = (Node) it.next(); + List list = xpath.selectNodes(input); + for (Node current : list) { mod.fireRule(current); } } /** - * Processes the result of the xpath expression. The xpath expression is - * evaluated against the provided input object. + * If input is a Node, this will processes all of the + * children of that node. If input is a List of + * Nodess, these nodes will be iterated and all children of + * each node will be processed. * - * @param input - * the input object - * @param xpath - * the xpath expression + * @param node the input object * @throws Exception * if something goes wrong - * @deprecated Use {@link Stylesheet#applyTemplates(Object, XPath)}instead. */ - public void applyTemplates(Object input, org.jaxen.XPath xpath) - throws Exception { - applyTemplates(input, xpath, this.modeName); + public void applyTemplates(Node node) throws Exception { + applyTemplates(node, this.modeName); } /** - * Processes the result of the xpath expression in the given mode. The xpath - * expression is evaluated against the provided input object. - * - * @param input - * the input object - * @param xpath - * the xpath expression - * @param mode - * the mode + * If input is a Node, this will processes all of the + * children of that node. If input is a List of + * Nodess, these nodes will be iterated and all children of + * each node will be processed. + * + * @param element the input object * @throws Exception * if something goes wrong - * @deprecated Use {@link Stylesheet#applyTemplates(Object, XPath, String)} - * instead. */ - public void applyTemplates(Object input, org.jaxen.XPath xpath, String mode) - throws Exception { - Mode mod = ruleManager.getMode(mode); + public void applyTemplates(Element element) throws Exception { + applyTemplates(element, this.modeName); + } - List list = xpath.selectNodes(input); - Iterator it = list.iterator(); - while (it.hasNext()) { - Node current = (Node) it.next(); - mod.fireRule(current); - } + /** + * If input is a Node, this will processes all of the + * children of that node. If input is a List of + * Nodess, these nodes will be iterated and all children of + * each node will be processed. + * + * @param document the input object + * @throws Exception + * if something goes wrong + */ + public void applyTemplates(Document document) throws Exception { + applyTemplates(document, this.modeName); } /** @@ -191,15 +157,13 @@ public class Stylesheet { * children of that node. If input is a List of * Nodess, these nodes will be iterated and all children of * each node will be processed. - * - * @param input - * the input object, this can either be a Node or - * a List + * + * @param list the input object * @throws Exception * if something goes wrong */ - public void applyTemplates(Object input) throws Exception { - applyTemplates(input, this.modeName); + public void applyTemplates(List list) throws Exception { + applyTemplates(list, this.modeName); } /** @@ -208,42 +172,82 @@ public class Stylesheet { * node. If input is a List of Nodess, these * nodes will be iterated and all children of each node will be processed. * - * @param input - * the input object, this can either be a Node or - * a List + * @param node the input object + * @param mode + * the mode + * @throws Exception + * if something goes wrong + */ + public void applyTemplates(Node node, String mode) throws Exception { + if (node instanceof Element) { + applyTemplates((Element) node, mode); + } else if (node instanceof Document) { + applyTemplates((Document) node, mode); + } + } + + /** + * Processes the input object in the given mode. If input is a + * Node, this will processes all of the children of that + * node. If input is a List of Nodess, these + * nodes will be iterated and all children of each node will be processed. + * + * @param element the input object * @param mode * the mode * @throws Exception * if something goes wrong */ - public void applyTemplates(Object input, String mode) throws Exception { + public void applyTemplates(Element element, String mode) throws Exception { Mode mod = ruleManager.getMode(mode); - if (input instanceof Element) { - // iterate through all children - Element element = (Element) input; - for (int i = 0, size = element.nodeCount(); i < size; i++) { - Node node = element.node(i); - mod.fireRule(node); - } - } else if (input instanceof Document) { - // iterate through all children - Document document = (Document) input; - for (int i = 0, size = document.nodeCount(); i < size; i++) { - Node node = document.node(i); - mod.fireRule(node); - } - } else if (input instanceof List) { - List list = (List) input; + // iterate through all children + for (int i = 0, size = element.nodeCount(); i < size; i++) { + Node node = element.node(i); + mod.fireRule(node); + } + } - for (int i = 0, size = list.size(); i < size; i++) { - Object object = list.get(i); + /** + * Processes the input object in the given mode. If input is a + * Node, this will processes all of the children of that + * node. If input is a List of Nodess, these + * nodes will be iterated and all children of each node will be processed. + * + * @param document the input object + * @param mode + * the mode + * @throws Exception + * if something goes wrong + */ + public void applyTemplates(Document document, String mode) throws Exception { + Mode mod = ruleManager.getMode(mode); + + // iterate through all children + for (int i = 0, size = document.nodeCount(); i < size; i++) { + Node node = document.node(i); + mod.fireRule(node); + } + } - if (object instanceof Element) { - applyTemplates((Element) object, mode); - } else if (object instanceof Document) { - applyTemplates((Document) object, mode); - } + /** + * Processes the input object in the given mode. If input is a + * Node, this will processes all of the children of that + * node. If input is a List of Nodess, these + * nodes will be iterated and all children of each node will be processed. + * + * @param list list of Elements or Documents + * @param mode + * the mode + * @throws Exception + * if something goes wrong + */ + public void applyTemplates(List list, String mode) throws Exception { + for (Node node : list) { + if (node instanceof Element) { + applyTemplates((Element) node, mode); + } else if (node instanceof Document) { + applyTemplates((Document) node, mode); } } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/package-info.java new file mode 100644 index 000000000..e9a4d74eb --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/package-info.java @@ -0,0 +1,5 @@ +/** + * A {@link org.dom4j.rule.Pattern} based XML rule engine which implements the full XSLT processing model while allowing any {@link org.dom4j.rule.Action} + * to be fired if a pattern matches. This package can be used as a the base for a full XSLT implementation or alternatives, such as a JSP custom tag implementation of XSLT. + */ +package org.dom4j.rule; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/package.html b/fine-org-dom4j/src/main/java/org/dom4j/rule/package.html deleted file mode 100644 index ba5db9b67..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/package.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -

A {@link org.dom4j.rule.Pattern} based XML rule engine which implements -the full XSLT processing model while allowing any {@link org.dom4j.rule.Action} -to be fired if a pattern matches. -This package can be used as a the base for a full XSLT implementation -or alternatives, such as a JSP custom tag implementation of XSLT. -

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/DefaultPattern.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/DefaultPattern.java index 482b20a72..913ef1c5d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/DefaultPattern.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/DefaultPattern.java @@ -22,7 +22,7 @@ import org.dom4j.rule.Pattern; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.6 $ */ public class DefaultPattern implements Pattern { private NodeFilter filter; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/NodeTypePattern.java b/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/NodeTypePattern.java index 5ec208b0b..fdb61cfa0 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/NodeTypePattern.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/rule/pattern/NodeTypePattern.java @@ -17,7 +17,7 @@ import org.dom4j.rule.Pattern; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class NodeTypePattern implements Pattern { /** A pattern which matches any Attribute node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/BranchTreeNode.java b/fine-org-dom4j/src/main/java/org/dom4j/swing/BranchTreeNode.java index ed3588da1..8f2bd393a 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/swing/BranchTreeNode.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/swing/BranchTreeNode.java @@ -26,11 +26,11 @@ import org.dom4j.Node; * * @author James Strachan * @author Jakob Jenkov - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class BranchTreeNode extends LeafTreeNode { /** Stores the child tree nodes */ - protected List children; + protected List children; public BranchTreeNode() { } @@ -45,15 +45,15 @@ public class BranchTreeNode extends LeafTreeNode { // TreeNode methods // ------------------------------------------------------------------------- - public Enumeration children() { - return new Enumeration() { + public Enumeration children() { + return new Enumeration() { private int index = -1; public boolean hasMoreElements() { return (index + 1) < getChildCount(); } - public Object nextElement() { + public TreeNode nextElement() { return getChildAt(++index); } }; @@ -91,7 +91,7 @@ public class BranchTreeNode extends LeafTreeNode { * * @return DOCUMENT ME! */ - protected List getChildList() { + protected List getChildList() { // for now lets just create the children once, the first time they // are asked for. // XXXX - we may wish to detect inconsistencies here.... @@ -107,11 +107,11 @@ public class BranchTreeNode extends LeafTreeNode { * * @return DOCUMENT ME! */ - protected List createChildList() { + protected List createChildList() { // add attributes and content as children? Branch branch = getXmlBranch(); int size = branch.nodeCount(); - List childList = new ArrayList(size); + List childList = new ArrayList(size); for (int i = 0; i < size; i++) { Node node = branch.node(i); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/DocumentTreeModel.java b/fine-org-dom4j/src/main/java/org/dom4j/swing/DocumentTreeModel.java index d8d5ca936..779688c4c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/swing/DocumentTreeModel.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/swing/DocumentTreeModel.java @@ -19,7 +19,7 @@ import org.dom4j.Document; * * @author James Strachan * @author Jakob Jenkov - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class DocumentTreeModel extends DefaultTreeModel { /** The document for this model */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/LeafTreeNode.java b/fine-org-dom4j/src/main/java/org/dom4j/swing/LeafTreeNode.java index 81b61211c..69b546513 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/swing/LeafTreeNode.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/swing/LeafTreeNode.java @@ -21,10 +21,10 @@ import org.dom4j.Node; * * @author James Strachan * @author Jakob Jenkov - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class LeafTreeNode implements TreeNode { - protected static final Enumeration EMPTY_ENUMERATION = new Enumeration() { + protected static final Enumeration EMPTY_ENUMERATION = new Enumeration() { public boolean hasMoreElements() { return false; } @@ -54,7 +54,7 @@ public class LeafTreeNode implements TreeNode { // TreeNode methods // ------------------------------------------------------------------------- - public Enumeration children() { + public Enumeration children() { return EMPTY_ENUMERATION; } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableColumnDefinition.java b/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableColumnDefinition.java index 6e7f14537..60e285017 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableColumnDefinition.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableColumnDefinition.java @@ -19,7 +19,7 @@ import org.dom4j.XPath; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class XMLTableColumnDefinition implements Serializable { public static final int OBJECT_TYPE = 0; @@ -77,7 +77,7 @@ public class XMLTableColumnDefinition implements Serializable { return OBJECT_TYPE; } - public Class getColumnClass() { + public Class getColumnClass() { switch (type) { case STRING_TYPE: return String.class; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableDefinition.java b/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableDefinition.java index 46b826554..19ed35cef 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableDefinition.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableDefinition.java @@ -28,20 +28,20 @@ import org.jaxen.VariableContext; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ public class XMLTableDefinition implements Serializable, VariableContext { /** Holds value of property rowXPath. */ private XPath rowXPath; /** The columns to display in this table */ - private List columns = new ArrayList(); + private List columns = new ArrayList(); /** integer index array cache */ private XMLTableColumnDefinition[] columnArray; /** name index cache */ - private Map columnNameIndex; + private Map columnNameIndex; /** for cross-row variables */ private VariableContext variableContext; @@ -76,9 +76,9 @@ public class XMLTableDefinition implements Serializable, VariableContext { XMLTableDefinition answer = new XMLTableDefinition(); answer.setRowExpression(definition.attributeValue("select")); - for (Iterator iter = definition.elementIterator("column"); iter + for (Iterator iter = definition.elementIterator("column"); iter .hasNext();) { - Element element = (Element) iter.next(); + Element element = iter.next(); String expression = element.attributeValue("select"); String name = element.getText(); String typeName = element.attributeValue("type", "string"); @@ -95,7 +95,7 @@ public class XMLTableDefinition implements Serializable, VariableContext { return answer; } - public Class getColumnClass(int columnIndex) { + public Class getColumnClass(int columnIndex) { return getColumn(columnIndex).getColumnClass(); } @@ -205,11 +205,9 @@ public class XMLTableDefinition implements Serializable, VariableContext { public XMLTableColumnDefinition getColumn(String columnName) { if (columnNameIndex == null) { - columnNameIndex = new HashMap(); + columnNameIndex = new HashMap(); - for (Iterator it = columns.iterator(); it.hasNext();) { - XMLTableColumnDefinition column = (XMLTableColumnDefinition) it - .next(); + for (XMLTableColumnDefinition column : columns) { columnNameIndex.put(column.getName(), column); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableModel.java b/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableModel.java index dc4477770..d3151327e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableModel.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/swing/XMLTableModel.java @@ -13,6 +13,7 @@ import javax.swing.table.AbstractTableModel; import org.dom4j.Document; import org.dom4j.Element; +import org.dom4j.Node; import org.dom4j.XPath; /** @@ -21,7 +22,7 @@ import org.dom4j.XPath; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ public class XMLTableModel extends AbstractTableModel { /** Holds value of property definition. */ @@ -31,7 +32,7 @@ public class XMLTableModel extends AbstractTableModel { private Object source; /** The rows evaluated from the row XPath expression */ - private List rows; + private List rows; /** * Creates a TableModel from an XML table definition document and an XML @@ -68,7 +69,7 @@ public class XMLTableModel extends AbstractTableModel { return getRows().get(rowIndex); } - public List getRows() { + public List getRows() { if (rows == null) { rows = definition.getRowXPath().selectNodes(source); } @@ -78,7 +79,7 @@ public class XMLTableModel extends AbstractTableModel { // TableModel interface // ------------------------------------------------------------------------- - public Class getColumnClass(int columnIndex) { + public Class getColumnClass(int columnIndex) { return definition.getColumnClass(columnIndex); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/swing/package-info.java new file mode 100644 index 000000000..2b17ec3e4 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/swing/package-info.java @@ -0,0 +1,4 @@ +/** + * A collection of adapters to allow easy integration with dom4j XML documents and Swing such as TreeModels and TableModels. + */ +package org.dom4j.swing; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/swing/package.html b/fine-org-dom4j/src/main/java/org/dom4j/swing/package.html deleted file mode 100644 index e5d074bae..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/swing/package.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -

A collection of adapters to allow easy integration with dom4j - XML documents and Swing such as TreeModels and TableModels.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractAttribute.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractAttribute.java index 9c0afb5a6..af58d1906 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractAttribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractAttribute.java @@ -7,23 +7,19 @@ package org.dom4j.tree; +import org.dom4j.*; + import java.io.IOException; import java.io.Writer; -import org.dom4j.Attribute; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.Node; -import org.dom4j.Visitor; - /** *

* AbstractNamespace is an abstract base class for tree * implementors to use for implementation inheritence. *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.21 $ */ public abstract class AbstractAttribute extends AbstractNode implements Attribute { @@ -99,7 +95,7 @@ public abstract class AbstractAttribute extends AbstractNode implements } public String getPath(Element context) { - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); Element parent = getParent(); @@ -124,7 +120,7 @@ public abstract class AbstractAttribute extends AbstractNode implements } public String getUniquePath(Element context) { - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); Element parent = getParent(); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractBranch.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractBranch.java index 6af26d677..e34f804cd 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractBranch.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractBranch.java @@ -7,28 +7,19 @@ package org.dom4j.tree; +import org.dom4j.*; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; -import org.dom4j.Branch; -import org.dom4j.Comment; -import org.dom4j.Element; -import org.dom4j.IllegalAddException; -import org.dom4j.Namespace; -import org.dom4j.Node; -import org.dom4j.ProcessingInstruction; -import org.dom4j.QName; - /** - *

* AbstractBranch is an abstract base class for tree implementors * to use for implementation inheritence. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.44 $ */ public abstract class AbstractBranch extends AbstractNode implements Branch { protected static final int DEFAULT_CONTENT_LIST_SIZE = 5; @@ -36,22 +27,24 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { public AbstractBranch() { } + @Override public boolean isReadOnly() { return false; } + @Override public boolean hasContent() { return nodeCount() > 0; } - public List content() { - List backingList = contentList(); + public List content() { + List backingList = contentList(); - return new ContentListFacade(this, backingList); + return new ContentListFacade(this, backingList); } public String getText() { - List content = contentList(); + List content = contentList(); if (content != null) { int size = content.size(); @@ -64,7 +57,7 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { // optimised to avoid StringBuffer creation return firstText; } else { - StringBuffer buffer = new StringBuffer(firstText); + StringBuilder buffer = new StringBuilder(firstText); for (int i = 1; i < size; i++) { Object node = content.get(i); @@ -144,7 +137,7 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { public String getTextTrim() { String text = getText(); - StringBuffer textContent = new StringBuffer(); + StringBuilder textContent = new StringBuilder(); StringTokenizer tokenizer = new StringTokenizer(text); while (tokenizer.hasMoreTokens()) { @@ -159,9 +152,8 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { return textContent.toString(); } - public void setProcessingInstructions(List listOfPIs) { - for (Iterator iter = listOfPIs.iterator(); iter.hasNext();) { - ProcessingInstruction pi = (ProcessingInstruction) iter.next(); + public void setProcessingInstructions(List listOfPIs) { + for (ProcessingInstruction pi : listOfPIs) { addNode(pi); } } @@ -292,17 +284,7 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { } public Node node(int index) { - Object object = contentList().get(index); - - if (object instanceof Node) { - return (Node) object; - } - - if (object instanceof String) { - return getDocumentFactory().createText(object.toString()); - } - - return null; + return contentList().get(index); } public int nodeCount() { @@ -313,7 +295,7 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { return contentList().indexOf(node); } - public Iterator nodeIterator() { + public Iterator nodeIterator() { return contentList().iterator(); } @@ -338,7 +320,7 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { * * @return the internal List used to manage the content */ - protected abstract List contentList(); + protected abstract List contentList(); /** * A Factory Method pattern which creates a List implementation used to @@ -346,8 +328,8 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { * * @return DOCUMENT ME! */ - protected List createContentList() { - return new ArrayList(DEFAULT_CONTENT_LIST_SIZE); + protected List createContentList() { + return new ArrayList(DEFAULT_CONTENT_LIST_SIZE); } /** @@ -359,31 +341,33 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { * * @return DOCUMENT ME! */ - protected List createContentList(int size) { - return new ArrayList(size); + protected List createContentList(int size) { + return new ArrayList(size); } /** * A Factory Method pattern which creates a BackedList implementation used * to store results of a filtered content query. - * + * + * @param DOCUMENT ME! * @return DOCUMENT ME! */ - protected BackedList createResultList() { - return new BackedList(this, contentList()); + protected BackedList createResultList() { + return new BackedList(this, contentList()); } /** * A Factory Method pattern which creates a BackedList implementation which * contains a single result * + * @param DOCUMENT ME! * @param result * DOCUMENT ME! * * @return DOCUMENT ME! */ - protected List createSingleResultList(Object result) { - BackedList list = new BackedList(this, contentList(), 1); + protected List createSingleResultList(T result) { + BackedList list = new BackedList(this, contentList(), 1); list.addLocal(result); return list; @@ -392,11 +376,12 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { /** * A Factory Method pattern which creates an empty a BackedList * implementation - * + * + * @param DOCUMENT ME! * @return DOCUMENT ME! */ - protected List createEmptyList() { - return new BackedList(this, contentList(), 0); + protected List createEmptyList() { + return new BackedList(this, contentList(), 0); } protected abstract void addNode(Node node); @@ -428,14 +413,10 @@ public abstract class AbstractBranch extends AbstractNode implements Branch { * have its parent and document relationships cleared */ protected void contentRemoved() { - List content = contentList(); - - for (int i = 0, size = content.size(); i < size; i++) { - Object object = content.get(i); + List content = contentList(); - if (object instanceof Node) { - childRemoved((Node) object); - } + for (Node node : content) { + childRemoved(node); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCDATA.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCDATA.java index e18a15af7..4723c6a0f 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCDATA.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCDATA.java @@ -21,7 +21,7 @@ import org.dom4j.Visitor; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public abstract class AbstractCDATA extends AbstractCharacterData implements CDATA { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCharacterData.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCharacterData.java index d6f3b1c60..9a05271be 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCharacterData.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractCharacterData.java @@ -17,7 +17,7 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public abstract class AbstractCharacterData extends AbstractNode implements CharacterData { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractComment.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractComment.java index fede87a63..fa18422f6 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractComment.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractComment.java @@ -21,7 +21,7 @@ import org.dom4j.Visitor; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.13 $ */ public abstract class AbstractComment extends AbstractCharacterData implements Comment { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocument.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocument.java index d5636a128..265ec0860 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocument.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocument.java @@ -7,26 +7,16 @@ package org.dom4j.tree; +import org.dom4j.*; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + import java.io.IOException; import java.io.StringWriter; import java.io.Writer; -import java.util.Iterator; import java.util.List; import java.util.Map; -import org.dom4j.Comment; -import org.dom4j.Document; -import org.dom4j.DocumentType; -import org.dom4j.Element; -import org.dom4j.IllegalAddException; -import org.dom4j.Node; -import org.dom4j.ProcessingInstruction; -import org.dom4j.QName; -import org.dom4j.Text; -import org.dom4j.Visitor; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.XMLWriter; - /** *

* AbstractDocument is an abstract base class for tree @@ -34,7 +24,7 @@ import org.dom4j.io.XMLWriter; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.33 $ */ public abstract class AbstractDocument extends AbstractBranch implements Document { @@ -115,20 +105,11 @@ public abstract class AbstractDocument extends AbstractBranch implements } // visit content - List content = content(); + List content = content(); if (content != null) { - for (Iterator iter = content.iterator(); iter.hasNext();) { - Object object = iter.next(); - - if (object instanceof String) { - Text text = getDocumentFactory() - .createText((String) object); - visitor.visit(text); - } else { - Node node = (Node) object; - node.accept(visitor); - } + for (Node node : content) { + node.accept(visitor); } } } @@ -160,7 +141,7 @@ public abstract class AbstractDocument extends AbstractBranch implements return this; } - public Document addProcessingInstruction(String target, Map data) { + public Document addProcessingInstruction(String target, Map data) { ProcessingInstruction node = getDocumentFactory() .createProcessingInstruction(target, data); add(node); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocumentType.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocumentType.java index 0444113b6..e070a8713 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocumentType.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractDocumentType.java @@ -7,15 +7,16 @@ package org.dom4j.tree; +import org.dom4j.DocumentType; +import org.dom4j.Element; +import org.dom4j.Visitor; +import org.dom4j.dtd.Decl; + import java.io.IOException; import java.io.Writer; import java.util.Iterator; import java.util.List; -import org.dom4j.DocumentType; -import org.dom4j.Element; -import org.dom4j.Visitor; - /** *

* AbstractDocumentType is an abstract base class for tree @@ -23,7 +24,7 @@ import org.dom4j.Visitor; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.17 $ */ public abstract class AbstractDocumentType extends AbstractNode implements DocumentType { @@ -59,14 +60,14 @@ public abstract class AbstractDocumentType extends AbstractNode implements * @return DOCUMENT ME! */ public String getText() { - List list = getInternalDeclarations(); + List list = getInternalDeclarations(); if ((list != null) && (list.size() > 0)) { - StringBuffer buffer = new StringBuffer(); - Iterator iter = list.iterator(); + StringBuilder buffer = new StringBuilder(); + Iterator iter = list.iterator(); if (iter.hasNext()) { - Object decl = iter.next(); + Decl decl = iter.next(); buffer.append(decl.toString()); while (iter.hasNext()) { @@ -87,7 +88,7 @@ public abstract class AbstractDocumentType extends AbstractNode implements } public String asXML() { - StringBuffer buffer = new StringBuffer(" list = getInternalDeclarations(); if ((list != null) && (list.size() > 0)) { writer.write(" ["); - for (Iterator iter = list.iterator(); iter.hasNext();) { - Object decl = iter.next(); + for (Decl decl : list) { writer.write("\n "); writer.write(decl.toString()); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractElement.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractElement.java index 5e3c0c018..5fb4c86a7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractElement.java @@ -7,1643 +7,1492 @@ package org.dom4j.tree; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.dom4j.Attribute; -import org.dom4j.CDATA; -import org.dom4j.CharacterData; -import org.dom4j.Comment; -import org.dom4j.Document; -import org.dom4j.DocumentFactory; -import org.dom4j.Element; -import org.dom4j.Entity; -import org.dom4j.IllegalAddException; -import org.dom4j.Namespace; -import org.dom4j.Node; -import org.dom4j.ProcessingInstruction; -import org.dom4j.QName; -import org.dom4j.Text; -import org.dom4j.Visitor; +import org.dom4j.*; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; - import org.xml.sax.Attributes; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.*; + /** *

* AbstractElement is an abstract base class for tree * implementors to use for implementation inheritence. *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.80 $ */ +@SuppressWarnings("unused") public abstract class AbstractElement extends AbstractBranch implements - org.dom4j.Element { - /** The DocumentFactory instance used by default */ - private static final DocumentFactory DOCUMENT_FACTORY = DocumentFactory - .getInstance(); - - protected static final List EMPTY_LIST = Collections.EMPTY_LIST; - - protected static final Iterator EMPTY_ITERATOR = EMPTY_LIST.iterator(); - - protected static final boolean VERBOSE_TOSTRING = false; - - protected static final boolean USE_STRINGVALUE_SEPARATOR = false; - - public AbstractElement() { - } - - public short getNodeType() { - return ELEMENT_NODE; - } - - public boolean isRootElement() { - Document document = getDocument(); - - if (document != null) { - Element root = document.getRootElement(); - - if (root == this) { - return true; - } - } - - return false; - } - - public void setName(String name) { - setQName(getDocumentFactory().createQName(name)); - } - - public void setNamespace(Namespace namespace) { - setQName(getDocumentFactory().createQName(getName(), namespace)); - } - - /** - * Returns the XPath expression to match this Elements name which is - * getQualifiedName() if there is a namespace prefix defined or if no - * namespace is present then it is getName() or if a namespace is defined - * with no prefix then the expression is [name()='X'] where X = getName(). - * - * @return DOCUMENT ME! - */ - public String getXPathNameStep() { - String uri = getNamespaceURI(); - - if ((uri == null) || (uri.length() == 0)) { - return getName(); - } - - String prefix = getNamespacePrefix(); - - if ((prefix == null) || (prefix.length() == 0)) { - return "*[name()='" + getName() + "']"; - } - - return getQualifiedName(); - } - - public String getPath(Element context) { - if (this == context) { - return "."; - } - - Element parent = getParent(); - - if (parent == null) { - return "/" + getXPathNameStep(); - } else if (parent == context) { - return getXPathNameStep(); - } - - return parent.getPath(context) + "/" + getXPathNameStep(); - } - - public String getUniquePath(Element context) { - Element parent = getParent(); - - if (parent == null) { - return "/" + getXPathNameStep(); - } - - StringBuffer buffer = new StringBuffer(); - - if (parent != context) { - buffer.append(parent.getUniquePath(context)); - - buffer.append("/"); - } - - buffer.append(getXPathNameStep()); - - List mySiblings = parent.elements(getQName()); - - if (mySiblings.size() > 1) { - int idx = mySiblings.indexOf(this); - - if (idx >= 0) { - buffer.append("["); - - buffer.append(Integer.toString(++idx)); - - buffer.append("]"); - } - } - - return buffer.toString(); - } - - public String asXML() { - try { - StringWriter out = new StringWriter(); - XMLWriter writer = new XMLWriter(out, new OutputFormat()); - - writer.write(this); - writer.flush(); - - return out.toString(); - } catch (IOException e) { - throw new RuntimeException("IOException while generating " - + "textual representation: " + e.getMessage()); - } - } - - public void write(Writer out) throws IOException { - XMLWriter writer = new XMLWriter(out, new OutputFormat()); - writer.write(this); - } - - /** - *

- * accept method is the Visitor Pattern - * method. - *

- * - * @param visitor - * Visitor is the visitor. - */ - public void accept(Visitor visitor) { - visitor.visit(this); - - // visit attributes - for (int i = 0, size = attributeCount(); i < size; i++) { - Attribute attribute = attribute(i); - - visitor.visit(attribute); - } - - // visit content - for (int i = 0, size = nodeCount(); i < size; i++) { - Node node = node(i); - - node.accept(visitor); - } - } - - public String toString() { - String uri = getNamespaceURI(); - - if ((uri != null) && (uri.length() > 0)) { - if (VERBOSE_TOSTRING) { - return super.toString() + " [Element: <" + getQualifiedName() - + " uri: " + uri + " attributes: " + attributeList() - + " content: " + contentList() + " />]"; - } else { - return super.toString() + " [Element: <" + getQualifiedName() - + " uri: " + uri + " attributes: " + attributeList() - + "/>]"; - } - } else { - if (VERBOSE_TOSTRING) { - return super.toString() + " [Element: <" + getQualifiedName() - + " attributes: " + attributeList() + " content: " - + contentList() + " />]"; - } else { - return super.toString() + " [Element: <" + getQualifiedName() - + " attributes: " + attributeList() + "/>]"; - } - } - } - - // QName methods - // ------------------------------------------------------------------------- - public Namespace getNamespace() { - return getQName().getNamespace(); - } - - public String getName() { - return getQName().getName(); - } - - public String getNamespacePrefix() { - return getQName().getNamespacePrefix(); - } - - public String getNamespaceURI() { - return getQName().getNamespaceURI(); - } - - public String getQualifiedName() { - return getQName().getQualifiedName(); - } - - public Object getData() { - return getText(); - } - - public void setData(Object data) { - // ignore this method - } - - // Node methods - // ------------------------------------------------------------------------- - public Node node(int index) { - if (index >= 0) { - List list = contentList(); - - if (index >= list.size()) { - return null; - } - - Object node = list.get(index); - - if (node != null) { - if (node instanceof Node) { - return (Node) node; - } else { - return getDocumentFactory().createText(node.toString()); - } - } - } - - return null; - } - - public int indexOf(Node node) { - return contentList().indexOf(node); - } - - public int nodeCount() { - return contentList().size(); - } - - public Iterator nodeIterator() { - return contentList().iterator(); - } - - // Element methods - // ------------------------------------------------------------------------- - public Element element(String name) { - List list = contentList(); - - int size = list.size(); + org.dom4j.Element { + /** + * The DocumentFactory instance used by default + */ + private static final DocumentFactory DOCUMENT_FACTORY = DocumentFactory + .getInstance(); - for (int i = 0; i < size; i++) { - Object object = list.get(i); + protected static final boolean VERBOSE_TOSTRING = false; - if (object instanceof Element) { - Element element = (Element) object; + protected static final boolean USE_STRINGVALUE_SEPARATOR = false; - if (name.equals(element.getName())) { - return element; - } - } - } + public AbstractElement() { + } - return null; - } + public short getNodeType() { + return ELEMENT_NODE; + } - public Element element(QName qName) { - List list = contentList(); + public boolean isRootElement() { + Document document = getDocument(); - int size = list.size(); + if (document != null) { + Element root = document.getRootElement(); - for (int i = 0; i < size; i++) { - Object object = list.get(i); + if (root == this) { + return true; + } + } - if (object instanceof Element) { - Element element = (Element) object; + return false; + } - if (qName.equals(element.getQName())) { - return element; - } - } - } + public void setName(String name) { + setQName(getDocumentFactory().createQName(name)); + } - return null; - } + public void setNamespace(Namespace namespace) { + setQName(getDocumentFactory().createQName(getName(), namespace)); + } - public Element element(String name, Namespace namespace) { - return element(getDocumentFactory().createQName(name, namespace)); - } + /** + * Returns the XPath expression to match this Elements name which is + * getQualifiedName() if there is a namespace prefix defined or if no + * namespace is present then it is getName() or if a namespace is defined + * with no prefix then the expression is [name()='X'] where X = getName(). + * + * @return DOCUMENT ME! + */ + public String getXPathNameStep() { + String uri = getNamespaceURI(); - public List elements() { - List list = contentList(); + if ((uri == null) || (uri.length() == 0)) { + return getName(); + } - BackedList answer = createResultList(); + String prefix = getNamespacePrefix(); - int size = list.size(); + if ((prefix == null) || (prefix.length() == 0)) { + return "*[name()='" + getName() + "']"; + } - for (int i = 0; i < size; i++) { - Object object = list.get(i); + return getQualifiedName(); + } - if (object instanceof Element) { - answer.addLocal(object); - } - } + public String getPath(Element context) { + if (this == context) { + return "."; + } - return answer; - } + Element parent = getParent(); - public List elements(String name) { - List list = contentList(); + if (parent == null) { + return "/" + getXPathNameStep(); + } else if (parent == context) { + return getXPathNameStep(); + } + + return parent.getPath(context) + "/" + getXPathNameStep(); + } + + public String getUniquePath(Element context) { + Element parent = getParent(); + + if (parent == null) { + return "/" + getXPathNameStep(); + } + + StringBuilder buffer = new StringBuilder(); + + if (parent != context) { + buffer.append(parent.getUniquePath(context)); + + buffer.append("/"); + } + + buffer.append(getXPathNameStep()); + + List mySiblings = parent.elements(getQName()); + + if (mySiblings.size() > 1) { + int idx = mySiblings.indexOf(this); + + if (idx >= 0) { + buffer.append("["); + + buffer.append(Integer.toString(++idx)); + + buffer.append("]"); + } + } + + return buffer.toString(); + } + + public String asXML() { + try { + StringWriter out = new StringWriter(); + XMLWriter writer = new XMLWriter(out, new OutputFormat()); + + writer.write(this); + writer.flush(); + + return out.toString(); + } catch (IOException e) { + throw new RuntimeException("IOException while generating " + + "textual representation: " + e.getMessage()); + } + } + + public void write(Writer out) throws IOException { + XMLWriter writer = new XMLWriter(out, new OutputFormat()); + writer.write(this); + } + + /** + *

+ * accept method is the Visitor Pattern + * method. + *

+ * + * @param visitor Visitor is the visitor. + */ + public void accept(Visitor visitor) { + visitor.visit(this); + + // visit attributes + for (int i = 0, size = attributeCount(); i < size; i++) { + Attribute attribute = attribute(i); + + visitor.visit(attribute); + } + + // visit content + for (int i = 0, size = nodeCount(); i < size; i++) { + Node node = node(i); + + node.accept(visitor); + } + } + + public String toString() { + String uri = getNamespaceURI(); + + if ((uri != null) && (uri.length() > 0)) { + if (VERBOSE_TOSTRING) { + return super.toString() + " [Element: <" + getQualifiedName() + + " uri: " + uri + " attributes: " + attributeList() + + " content: " + contentList() + " />]"; + } else { + return super.toString() + " [Element: <" + getQualifiedName() + + " uri: " + uri + " attributes: " + attributeList() + + "/>]"; + } + } else { + if (VERBOSE_TOSTRING) { + return super.toString() + " [Element: <" + getQualifiedName() + + " attributes: " + attributeList() + " content: " + + contentList() + " />]"; + } else { + return super.toString() + " [Element: <" + getQualifiedName() + + " attributes: " + attributeList() + "/>]"; + } + } + } + + // QName methods + // ------------------------------------------------------------------------- + public Namespace getNamespace() { + return getQName().getNamespace(); + } + + public String getName() { + return getQName().getName(); + } + + public String getNamespacePrefix() { + return getQName().getNamespacePrefix(); + } + + public String getNamespaceURI() { + return getQName().getNamespaceURI(); + } + + public String getQualifiedName() { + return getQName().getQualifiedName(); + } + + public Object getData() { + return getText(); + } + + public void setData(Object data) { + // ignore this method + } + + // Node methods + // ------------------------------------------------------------------------- + public Node node(int index) { + if (index >= 0) { + List list = contentList(); + + if (index >= list.size()) { + return null; + } + + Node node = list.get(index); + + if (node != null) { + return node; + } + } + + return null; + } + + @Override + public int indexOf(Node node) { + return contentList().indexOf(node); + } + + @Override + public int nodeCount() { + return contentList().size(); + } + + @Override + public Iterator nodeIterator() { + return contentList().iterator(); + } + + // Element methods + // ------------------------------------------------------------------------- + public Element element(String name) { + for (Node node : contentList()) { + if (node instanceof Element) { + Element element = (Element) node; + + if (name.equals(element.getName())) { + return element; + } + } + } + + return null; + } + + public Element element(QName qName) { + for (Node node : contentList()) { + if (node instanceof Element) { + Element element = (Element) node; + + if (qName.equals(element.getQName())) { + return element; + } + } + } + + return null; + } + + public Element element(String name, Namespace namespace) { + return element(getDocumentFactory().createQName(name, namespace)); + } + + public List elements() { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + if (node instanceof Element) { + answer.addLocal((Element) node); + } + } + + return answer; + } + + public List elements(String name) { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + if (node instanceof Element) { + Element element = (Element) node; + + if (name.equals(element.getName())) { + answer.addLocal(element); + } + } + } + + return answer; + } + + public List elements(QName qName) { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + if (node instanceof Element) { + Element element = (Element) node; + + if (qName.equals(element.getQName())) { + answer.addLocal(element); + } + } + } + + return answer; + } + + public List elements(String name, Namespace namespace) { + return elements(getDocumentFactory().createQName(name, namespace)); + } + + public Iterator elementIterator() { + List list = elements(); + + return list.iterator(); + } + + public Iterator elementIterator(String name) { + List list = elements(name); + + return list.iterator(); + } + + public Iterator elementIterator(QName qName) { + List list = elements(qName); + + return list.iterator(); + } + + public Iterator elementIterator(String name, Namespace ns) { + return elementIterator(getDocumentFactory().createQName(name, ns)); + } - BackedList answer = createResultList(); + // Attribute methods + // ------------------------------------------------------------------------- + public List attributes() { + return new ContentListFacade(this, attributeList()); + } - int size = list.size(); + public Iterator attributeIterator() { + return attributeList().iterator(); + } - for (int i = 0; i < size; i++) { - Object object = list.get(i); + public Attribute attribute(int index) { + return attributeList().get(index); + } - if (object instanceof Element) { - Element element = (Element) object; + public int attributeCount() { + return attributeList().size(); + } + + public Attribute attribute(String name) { + for (Attribute attribute : attributeList()) { + if (name.equals(attribute.getName())) { + return attribute; + } + } - if (name.equals(element.getName())) { - answer.addLocal(element); - } - } - } + return null; + } + + public Attribute attribute(QName qName) { + for (Attribute attribute : attributeList()) { + if (qName.equals(attribute.getQName())) { + return attribute; + } + } - return answer; - } + return null; + } - public List elements(QName qName) { - List list = contentList(); + public Attribute attribute(String name, Namespace namespace) { + return attribute(getDocumentFactory().createQName(name, namespace)); + } - BackedList answer = createResultList(); + /** + * This method provides a more optimal way of setting all the attributes on + * an Element particularly for use in {@link org.dom4j.io.SAXReader}. + * + * @param attributes DOCUMENT ME! + * @param namespaceStack DOCUMENT ME! + * @param noNamespaceAttributes DOCUMENT ME! + */ + public void setAttributes(Attributes attributes, + NamespaceStack namespaceStack, boolean noNamespaceAttributes) { + // now lets add all attribute values + int size = attributes.getLength(); + + if (size > 0) { + DocumentFactory factory = getDocumentFactory(); + + if (size == 1) { + // allow lazy construction of the List of Attributes + String name = attributes.getQName(0); + + if (noNamespaceAttributes || !name.startsWith("xmlns")) { + String attributeURI = attributes.getURI(0); + + String attributeLocalName = attributes.getLocalName(0); + + String attributeValue = attributes.getValue(0); + + QName attributeQName = namespaceStack.getAttributeQName( + attributeURI, attributeLocalName, name); + + add(factory.createAttribute(this, attributeQName, + attributeValue)); + } + } else { + List list = attributeList(size); + + list.clear(); + + for (int i = 0; i < size; i++) { + // optimised to avoid the call to attribute(QName) to + // lookup an attribute for a given QName + String attributeName = attributes.getQName(i); + + if (noNamespaceAttributes + || !attributeName.startsWith("xmlns")) { + String attributeURI = attributes.getURI(i); + + String attributeLocalName = attributes.getLocalName(i); + + String attributeValue = attributes.getValue(i); + + QName attributeQName = namespaceStack + .getAttributeQName(attributeURI, + attributeLocalName, attributeName); + + Attribute attribute = factory.createAttribute(this, + attributeQName, attributeValue); + + list.add(attribute); + + childAdded(attribute); + } + } + } + } + } + + public String attributeValue(String name) { + Attribute attrib = attribute(name); + + if (attrib == null) { + return null; + } else { + return attrib.getValue(); + } + } + + public String attributeValue(QName qName) { + Attribute attrib = attribute(qName); + + if (attrib == null) { + return null; + } else { + return attrib.getValue(); + } + } + + public String attributeValue(String name, String defaultValue) { + String answer = attributeValue(name); + + return (answer != null) ? answer : defaultValue; + } + + public String attributeValue(QName qName, String defaultValue) { + String answer = attributeValue(qName); + + return (answer != null) ? answer : defaultValue; + } + + /** + * DOCUMENT ME! + * + * @param name DOCUMENT ME! + * @param value DOCUMENT ME! + * @deprecated As of version 0.5. Please use {@link + * #addAttribute(String, String)} instead. WILL BE REMOVED IN + * dom4j-1.6 !! + */ + public void setAttributeValue(String name, String value) { + addAttribute(name, value); + } + + /** + * DOCUMENT ME! + * + * @param qName DOCUMENT ME! + * @param value DOCUMENT ME! + * @deprecated As of version 0.5. Please use {@link + * #addAttribute(String, String)} instead. WILL BE REMOVED IN + * dom4j-1.6 !! + */ + public void setAttributeValue(QName qName, String value) { + addAttribute(qName, value); + } + + public void add(Attribute attribute) { + if (attribute.getParent() != null) { + String message = "The Attribute already has an existing parent \"" + + attribute.getParent().getQualifiedName() + "\""; + + throw new IllegalAddException(this, attribute, message); + } + + if (attribute.getValue() == null) { + // try remove a previous attribute with the same + // name since adding an attribute with a null value + // is equivalent to removing it. + Attribute oldAttribute = attribute(attribute.getQName()); + + if (oldAttribute != null) { + remove(oldAttribute); + } + } else { + attributeList().add(attribute); + + childAdded(attribute); + } + } + + public boolean remove(Attribute attribute) { + List list = attributeList(); + + boolean answer = list.remove(attribute); + + if (answer) { + childRemoved(attribute); + } else { + // we may have a copy of the attribute + Attribute copy = attribute(attribute.getQName()); + + if (copy != null) { + list.remove(copy); + + answer = true; + } + } + + return answer; + } + + // Processing instruction API + // ------------------------------------------------------------------------- + public List processingInstructions() { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + if (node instanceof ProcessingInstruction) { + answer.addLocal((ProcessingInstruction) node); + } + } + + return answer; + } + + public List processingInstructions(String target) { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; + + if (target.equals(pi.getName())) { + answer.addLocal(pi); + } + } + } + + return answer; + } + + public ProcessingInstruction processingInstruction(String target) { + for (Node node : contentList()) { + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; + + if (target.equals(pi.getName())) { + return pi; + } + } + } - int size = list.size(); + return null; + } - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Element) { - Element element = (Element) object; - - if (qName.equals(element.getQName())) { - answer.addLocal(element); - } - } - } - - return answer; - } - - public List elements(String name, Namespace namespace) { - return elements(getDocumentFactory().createQName(name, namespace)); - } - - public Iterator elementIterator() { - List list = elements(); - - return list.iterator(); - } - - public Iterator elementIterator(String name) { - List list = elements(name); - - return list.iterator(); - } - - public Iterator elementIterator(QName qName) { - List list = elements(qName); - - return list.iterator(); - } - - public Iterator elementIterator(String name, Namespace ns) { - return elementIterator(getDocumentFactory().createQName(name, ns)); - } - - // Attribute methods - // ------------------------------------------------------------------------- - public List attributes() { - return new ContentListFacade(this, attributeList()); - } - - public Iterator attributeIterator() { - return attributeList().iterator(); - } - - public Attribute attribute(int index) { - return (Attribute) attributeList().get(index); - } - - public int attributeCount() { - return attributeList().size(); - } - - public Attribute attribute(String name) { - List list = attributeList(); - - int size = list.size(); - - for (int i = 0; i < size; i++) { - Attribute attribute = (Attribute) list.get(i); - - if (name.equals(attribute.getName())) { - return attribute; - } - } - - return null; - } - - public Attribute attribute(QName qName) { - List list = attributeList(); - - int size = list.size(); - - for (int i = 0; i < size; i++) { - Attribute attribute = (Attribute) list.get(i); - - if (qName.equals(attribute.getQName())) { - return attribute; - } - } - - return null; - } - - public Attribute attribute(String name, Namespace namespace) { - return attribute(getDocumentFactory().createQName(name, namespace)); - } - - /** - * This method provides a more optimal way of setting all the attributes on - * an Element particularly for use in {@link org.dom4j.io.SAXReader}. - * - * @param attributes - * DOCUMENT ME! - * @param namespaceStack - * DOCUMENT ME! - * @param noNamespaceAttributes - * DOCUMENT ME! - */ - public void setAttributes(Attributes attributes, - NamespaceStack namespaceStack, boolean noNamespaceAttributes) { - // now lets add all attribute values - int size = attributes.getLength(); - - if (size > 0) { - DocumentFactory factory = getDocumentFactory(); - - if (size == 1) { - // allow lazy construction of the List of Attributes - String name = attributes.getQName(0); - - if (noNamespaceAttributes || !name.startsWith("xmlns")) { - String attributeURI = attributes.getURI(0); - - String attributeLocalName = attributes.getLocalName(0); - - String attributeValue = attributes.getValue(0); - - QName attributeQName = namespaceStack.getAttributeQName( - attributeURI, attributeLocalName, name); - - add(factory.createAttribute(this, attributeQName, - attributeValue)); - } - } else { - List list = attributeList(size); - - list.clear(); - - for (int i = 0; i < size; i++) { - // optimised to avoid the call to attribute(QName) to - // lookup an attribute for a given QName - String attributeName = attributes.getQName(i); - - if (noNamespaceAttributes - || !attributeName.startsWith("xmlns")) { - String attributeURI = attributes.getURI(i); - - String attributeLocalName = attributes.getLocalName(i); - - String attributeValue = attributes.getValue(i); - - QName attributeQName = namespaceStack - .getAttributeQName(attributeURI, - attributeLocalName, attributeName); - - Attribute attribute = factory.createAttribute(this, - attributeQName, attributeValue); - - list.add(attribute); - - childAdded(attribute); - } - } - } - } - } - - public String attributeValue(String name) { - Attribute attrib = attribute(name); - - if (attrib == null) { - return null; - } else { - return attrib.getValue(); - } - } - - public String attributeValue(QName qName) { - Attribute attrib = attribute(qName); - - if (attrib == null) { - return null; - } else { - return attrib.getValue(); - } - } - - public String attributeValue(String name, String defaultValue) { - String answer = attributeValue(name); - - return (answer != null) ? answer : defaultValue; - } - - public String attributeValue(QName qName, String defaultValue) { - String answer = attributeValue(qName); - - return (answer != null) ? answer : defaultValue; - } - - /** - * DOCUMENT ME! - * - * @param name - * DOCUMENT ME! - * @param value - * DOCUMENT ME! - * - * @deprecated As of version 0.5. Please use {@link - * #addAttribute(String,String)} instead. WILL BE REMOVED IN - * dom4j-1.6 !! - */ - public void setAttributeValue(String name, String value) { - addAttribute(name, value); - } - - /** - * DOCUMENT ME! - * - * @param qName - * DOCUMENT ME! - * @param value - * DOCUMENT ME! - * - * @deprecated As of version 0.5. Please use {@link - * #addAttribute(String,String)} instead. WILL BE REMOVED IN - * dom4j-1.6 !! - */ - public void setAttributeValue(QName qName, String value) { - addAttribute(qName, value); - } + public boolean removeProcessingInstruction(String target) { + for (Iterator iter = contentList().iterator(); iter.hasNext(); ) { + Node node = iter.next(); - public void add(Attribute attribute) { - if (attribute.getParent() != null) { - String message = "The Attribute already has an existing parent \"" - + attribute.getParent().getQualifiedName() + "\""; + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; - throw new IllegalAddException(this, attribute, message); - } + if (target.equals(pi.getName())) { + iter.remove(); - if (attribute.getValue() == null) { - // try remove a previous attribute with the same - // name since adding an attribute with a null value - // is equivalent to removing it. - Attribute oldAttribute = attribute(attribute.getQName()); + return true; + } + } + } - if (oldAttribute != null) { - remove(oldAttribute); - } - } else { - attributeList().add(attribute); + return false; + } - childAdded(attribute); - } - } + // Content Model methods + // ------------------------------------------------------------------------- + public Node getXPathResult(int index) { + Node answer = node(index); - public boolean remove(Attribute attribute) { - List list = attributeList(); + if ((answer != null) && !answer.supportsParent()) { + return answer.asXPathResult(this); + } - boolean answer = list.remove(attribute); + return answer; + } - if (answer) { - childRemoved(attribute); - } else { - // we may have a copy of the attribute - Attribute copy = attribute(attribute.getQName()); + public Element addAttribute(String name, String value) { + // adding a null value is equivalent to removing the attribute + Attribute attribute = attribute(name); - if (copy != null) { - list.remove(copy); + if (value != null) { + if (attribute == null) { + add(getDocumentFactory().createAttribute(this, name, value)); + } else if (attribute.isReadOnly()) { + remove(attribute); - answer = true; - } - } + add(getDocumentFactory().createAttribute(this, name, value)); + } else { + attribute.setValue(value); + } + } else if (attribute != null) { + remove(attribute); + } - return answer; - } + return this; + } - // Processing instruction API - // ------------------------------------------------------------------------- - public List processingInstructions() { - List list = contentList(); + public Element addAttribute(QName qName, String value) { + // adding a null value is equivalent to removing the attribute + Attribute attribute = attribute(qName); - BackedList answer = createResultList(); + if (value != null) { + if (attribute == null) { + add(getDocumentFactory().createAttribute(this, qName, value)); + } else if (attribute.isReadOnly()) { + remove(attribute); - int size = list.size(); + add(getDocumentFactory().createAttribute(this, qName, value)); + } else { + attribute.setValue(value); + } + } else if (attribute != null) { + remove(attribute); + } - for (int i = 0; i < size; i++) { - Object object = list.get(i); + return this; + } - if (object instanceof ProcessingInstruction) { - answer.addLocal(object); - } - } + public Element addCDATA(String cdata) { + CDATA node = getDocumentFactory().createCDATA(cdata); - return answer; - } + addNewNode(node); - public List processingInstructions(String target) { - List list = contentList(); + return this; + } - BackedList answer = createResultList(); + public Element addComment(String comment) { + Comment node = getDocumentFactory().createComment(comment); - int size = list.size(); + addNewNode(node); - for (int i = 0; i < size; i++) { - Object object = list.get(i); + return this; + } - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + public Element addElement(String name) { + DocumentFactory factory = getDocumentFactory(); - if (target.equals(pi.getName())) { - answer.addLocal(pi); - } - } - } + int index = name.indexOf(":"); - return answer; - } + String prefix; - public ProcessingInstruction processingInstruction(String target) { - List list = contentList(); + String localName = name; - int size = list.size(); + Namespace namespace; - for (int i = 0; i < size; i++) { - Object object = list.get(i); + if (index > 0) { + prefix = name.substring(0, index); - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + localName = name.substring(index + 1); - if (target.equals(pi.getName())) { - return pi; - } - } - } + namespace = getNamespaceForPrefix(prefix); - return null; - } + if (namespace == null) { + throw new IllegalAddException("No such namespace prefix: " + + prefix + " is in scope on: " + this + + " so cannot add element: " + name); + } + } else { + namespace = getNamespaceForPrefix(""); + } - public boolean removeProcessingInstruction(String target) { - List list = contentList(); + Element node; - for (Iterator iter = list.iterator(); iter.hasNext();) { - Object object = iter.next(); + if (namespace != null) { + QName qname = factory.createQName(localName, namespace); - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + node = factory.createElement(qname); + } else { + node = factory.createElement(name); + } - if (target.equals(pi.getName())) { - iter.remove(); + addNewNode(node); - return true; - } - } - } + return node; + } - return false; - } + public Element addEntity(String name, String text) { + Entity node = getDocumentFactory().createEntity(name, text); - // Content Model methods - // ------------------------------------------------------------------------- - public Node getXPathResult(int index) { - Node answer = node(index); + addNewNode(node); - if ((answer != null) && !answer.supportsParent()) { - return answer.asXPathResult(this); - } + return this; + } - return answer; - } + public Element addNamespace(String prefix, String uri) { + Namespace node = getDocumentFactory().createNamespace(prefix, uri); - public Element addAttribute(String name, String value) { - // adding a null value is equivalent to removing the attribute - Attribute attribute = attribute(name); + addNewNode(node); - if (value != null) { - if (attribute == null) { - add(getDocumentFactory().createAttribute(this, name, value)); - } else if (attribute.isReadOnly()) { - remove(attribute); + return this; + } - add(getDocumentFactory().createAttribute(this, name, value)); - } else { - attribute.setValue(value); - } - } else if (attribute != null) { - remove(attribute); - } + public Element addProcessingInstruction(String target, String data) { + ProcessingInstruction node = getDocumentFactory() + .createProcessingInstruction(target, data); - return this; - } + addNewNode(node); - public Element addAttribute(QName qName, String value) { - // adding a null value is equivalent to removing the attribute - Attribute attribute = attribute(qName); + return this; + } - if (value != null) { - if (attribute == null) { - add(getDocumentFactory().createAttribute(this, qName, value)); - } else if (attribute.isReadOnly()) { - remove(attribute); + public Element addProcessingInstruction(String target, Map data) { + ProcessingInstruction node = getDocumentFactory() + .createProcessingInstruction(target, data); - add(getDocumentFactory().createAttribute(this, qName, value)); - } else { - attribute.setValue(value); - } - } else if (attribute != null) { - remove(attribute); - } + addNewNode(node); - return this; - } + return this; + } - public Element addCDATA(String cdata) { - CDATA node = getDocumentFactory().createCDATA(cdata); + public Element addText(String text) { + Text node = getDocumentFactory().createText(text); - addNewNode(node); + addNewNode(node); - return this; - } + return this; + } - public Element addComment(String comment) { - Comment node = getDocumentFactory().createComment(comment); + // polymorphic node methods + public void add(Node node) { + switch (node.getNodeType()) { + case ELEMENT_NODE: + add((Element) node); - addNewNode(node); + break; - return this; - } + case ATTRIBUTE_NODE: + add((Attribute) node); - public Element addElement(String name) { - DocumentFactory factory = getDocumentFactory(); + break; - int index = name.indexOf(":"); + case TEXT_NODE: + add((Text) node); - String prefix = ""; + break; - String localName = name; + case CDATA_SECTION_NODE: + add((CDATA) node); - Namespace namespace = null; + break; - if (index > 0) { - prefix = name.substring(0, index); + case ENTITY_REFERENCE_NODE: + add((Entity) node); - localName = name.substring(index + 1); + break; - namespace = getNamespaceForPrefix(prefix); + case PROCESSING_INSTRUCTION_NODE: + add((ProcessingInstruction) node); - if (namespace == null) { - throw new IllegalAddException("No such namespace prefix: " - + prefix + " is in scope on: " + this - + " so cannot add element: " + name); - } - } else { - namespace = getNamespaceForPrefix(""); - } + break; - Element node; + case COMMENT_NODE: + add((Comment) node); - if (namespace != null) { - QName qname = factory.createQName(localName, namespace); - - node = factory.createElement(qname); - } else { - node = factory.createElement(name); - } - - addNewNode(node); - - return node; - } - - public Element addEntity(String name, String text) { - Entity node = getDocumentFactory().createEntity(name, text); - - addNewNode(node); - - return this; - } - - public Element addNamespace(String prefix, String uri) { - Namespace node = getDocumentFactory().createNamespace(prefix, uri); - - addNewNode(node); - - return this; - } - - public Element addProcessingInstruction(String target, String data) { - ProcessingInstruction node = getDocumentFactory() - .createProcessingInstruction(target, data); - - addNewNode(node); - - return this; - } - - public Element addProcessingInstruction(String target, Map data) { - ProcessingInstruction node = getDocumentFactory() - .createProcessingInstruction(target, data); - - addNewNode(node); - - return this; - } - - public Element addText(String text) { - Text node = getDocumentFactory().createText(text); - - addNewNode(node); - - return this; - } - - // polymorphic node methods - public void add(Node node) { - switch (node.getNodeType()) { - case ELEMENT_NODE: - add((Element) node); - - break; - - case ATTRIBUTE_NODE: - add((Attribute) node); - - break; - - case TEXT_NODE: - add((Text) node); - - break; - - case CDATA_SECTION_NODE: - add((CDATA) node); - - break; - - case ENTITY_REFERENCE_NODE: - add((Entity) node); - - break; - - case PROCESSING_INSTRUCTION_NODE: - add((ProcessingInstruction) node); - - break; - - case COMMENT_NODE: - add((Comment) node); - - break; + break; /* * XXXX: to do! case DOCUMENT_TYPE_NODE: add((DocumentType) node); * break; */ - case NAMESPACE_NODE: - add((Namespace) node); + case NAMESPACE_NODE: + add((Namespace) node); - break; + break; - default: - invalidNodeTypeAddException(node); - } - } + default: + invalidNodeTypeAddException(node); + } + } - public boolean remove(Node node) { - switch (node.getNodeType()) { - case ELEMENT_NODE: - return remove((Element) node); + public boolean remove(Node node) { + switch (node.getNodeType()) { + case ELEMENT_NODE: + return remove((Element) node); - case ATTRIBUTE_NODE: - return remove((Attribute) node); + case ATTRIBUTE_NODE: + return remove((Attribute) node); - case TEXT_NODE: - return remove((Text) node); + case TEXT_NODE: + return remove((Text) node); - case CDATA_SECTION_NODE: - return remove((CDATA) node); + case CDATA_SECTION_NODE: + return remove((CDATA) node); - case ENTITY_REFERENCE_NODE: - return remove((Entity) node); + case ENTITY_REFERENCE_NODE: + return remove((Entity) node); - case PROCESSING_INSTRUCTION_NODE: - return remove((ProcessingInstruction) node); + case PROCESSING_INSTRUCTION_NODE: + return remove((ProcessingInstruction) node); - case COMMENT_NODE: - return remove((Comment) node); + case COMMENT_NODE: + return remove((Comment) node); /* * case DOCUMENT_TYPE_NODE: return remove((DocumentType) node); */ - case NAMESPACE_NODE: - return remove((Namespace) node); - - default: - return false; - } - } - - // typesafe versions using node classes - public void add(CDATA cdata) { - addNode(cdata); - } - - public void add(Comment comment) { - addNode(comment); - } - - public void add(Element element) { - addNode(element); - } - - public void add(Entity entity) { - addNode(entity); - } - - public void add(Namespace namespace) { - addNode(namespace); - } - - public void add(ProcessingInstruction pi) { - addNode(pi); - } - - public void add(Text text) { - addNode(text); - } - - public boolean remove(CDATA cdata) { - return removeNode(cdata); - } - - public boolean remove(Comment comment) { - return removeNode(comment); - } - - public boolean remove(Element element) { - return removeNode(element); - } - - public boolean remove(Entity entity) { - return removeNode(entity); - } - - public boolean remove(Namespace namespace) { - return removeNode(namespace); - } - - public boolean remove(ProcessingInstruction pi) { - return removeNode(pi); - } - - public boolean remove(Text text) { - return removeNode(text); - } - - // Helper methods - // ------------------------------------------------------------------------- - public boolean hasMixedContent() { - List content = contentList(); - - if ((content == null) || content.isEmpty() || (content.size() < 2)) { - return false; - } - - Class prevClass = null; - - for (Iterator iter = content.iterator(); iter.hasNext();) { - Object object = iter.next(); - - Class newClass = object.getClass(); - - if (newClass != prevClass) { - if (prevClass != null) { - return true; - } - - prevClass = newClass; - } - } - - return false; - } - - public boolean isTextOnly() { - List content = contentList(); - - if ((content == null) || content.isEmpty()) { - return true; - } - - for (Iterator iter = content.iterator(); iter.hasNext();) { - Object object = iter.next(); - - if (!(object instanceof CharacterData) - && !(object instanceof String)) { - return false; - } - } - - return true; - } - - public void setText(String text) { - /* remove all text nodes */ - List allContent = contentList(); - - if (allContent != null) { - Iterator it = allContent.iterator(); - - while (it.hasNext()) { - Node node = (Node) it.next(); - - switch (node.getNodeType()) { - case CDATA_SECTION_NODE: - - // case ENTITY_NODE: - case ENTITY_REFERENCE_NODE: - case TEXT_NODE: - it.remove(); - - default: - break; - } - } - } - - addText(text); - } - - public String getStringValue() { - List list = contentList(); - - int size = list.size(); - - if (size > 0) { - if (size == 1) { - // optimised to avoid StringBuffer creation - return getContentAsStringValue(list.get(0)); - } else { - StringBuffer buffer = new StringBuffer(); - - for (int i = 0; i < size; i++) { - Object node = list.get(i); - - String string = getContentAsStringValue(node); - - if (string.length() > 0) { - if (USE_STRINGVALUE_SEPARATOR) { - if (buffer.length() > 0) { - buffer.append(' '); - } - } - - buffer.append(string); - } - } - - return buffer.toString(); - } - } - - return ""; - } - - /** - * Puts all Text nodes in the full depth of the sub-tree - * underneath this Node, including attribute nodes, into a - * "normal" form where only structure (e.g., elements, comments, processing - * instructions, CDATA sections, and entity references) separates - * Text nodes, i.e., there are neither adjacent - * Text nodes nor empty Text nodes. This can - * be used to ensure that the DOM view of a document is the same as if it - * were saved and re-loaded, and is useful when operations (such as XPointer - * lookups) that depend on a particular document tree structure are to be - * used.In cases where the document contains CDATASections, - * the normalize operation alone may not be sufficient, since XPointers do - * not differentiate between Text nodes and - * CDATASection nodes. - * - * @since DOM Level 2 - */ - public void normalize() { - List content = contentList(); - - Text previousText = null; + case NAMESPACE_NODE: + return remove((Namespace) node); - int i = 0; + default: + return false; + } + } - while (i < content.size()) { - Node node = (Node) content.get(i); + // typesafe versions using node classes + public void add(CDATA cdata) { + addNode(cdata); + } - if (node instanceof Text) { - Text text = (Text) node; + public void add(Comment comment) { + addNode(comment); + } - if (previousText != null) { - previousText.appendText(text.getText()); + public void add(Element element) { + addNode(element); + } - remove(text); - } else { - String value = text.getText(); + public void add(Entity entity) { + addNode(entity); + } - // only remove empty Text nodes, not whitespace nodes - // if ( value == null || value.trim().length() <= 0 ) { - if ((value == null) || (value.length() <= 0)) { - remove(text); - } else { - previousText = text; + public void add(Namespace namespace) { + addNode(namespace); + } - i++; - } - } - } else { - if (node instanceof Element) { - Element element = (Element) node; + public void add(ProcessingInstruction pi) { + addNode(pi); + } - element.normalize(); - } + public void add(Text text) { + addNode(text); + } - previousText = null; + public boolean remove(CDATA cdata) { + return removeNode(cdata); + } - i++; - } - } - } + public boolean remove(Comment comment) { + return removeNode(comment); + } - public String elementText(String name) { - Element element = element(name); + public boolean remove(Element element) { + return removeNode(element); + } - return (element != null) ? element.getText() : null; - } + public boolean remove(Entity entity) { + return removeNode(entity); + } - public String elementText(QName qName) { - Element element = element(qName); + public boolean remove(Namespace namespace) { + return removeNode(namespace); + } - return (element != null) ? element.getText() : null; - } + public boolean remove(ProcessingInstruction pi) { + return removeNode(pi); + } - public String elementTextTrim(String name) { - Element element = element(name); + public boolean remove(Text text) { + return removeNode(text); + } - return (element != null) ? element.getTextTrim() : null; - } + // Helper methods + // ------------------------------------------------------------------------- + public boolean hasMixedContent() { + List content = contentList(); - public String elementTextTrim(QName qName) { - Element element = element(qName); + if ((content == null) || content.isEmpty() || (content.size() < 2)) { + return false; + } + + Class prevClass = null; + + for (Node node : content) { + Class newClass = node.getClass(); + + if (newClass != prevClass) { + if (prevClass != null) { + return true; + } + + prevClass = newClass; + } + } + + return false; + } + + public boolean isTextOnly() { + List content = contentList(); + + if ((content == null) || content.isEmpty()) { + return true; + } + + for (Node object : content) { + if (!(object instanceof CharacterData)) { + return false; + } + } + + return true; + } + + public void setText(String text) { + /* remove all text nodes */ + List allContent = contentList(); + + if (allContent != null) { + Iterator it = allContent.iterator(); + + while (it.hasNext()) { + Node node = it.next(); + + switch (node.getNodeType()) { + case CDATA_SECTION_NODE: + + // case ENTITY_NODE: + case ENTITY_REFERENCE_NODE: + case TEXT_NODE: + it.remove(); + + default: + break; + } + } + } + + addText(text); + } + + public String getStringValue() { + List list = contentList(); + + int size = list.size(); + + if (size > 0) { + if (size == 1) { + // optimised to avoid StringBuffer creation + return getContentAsStringValue(list.get(0)); + } else { + StringBuilder buffer = new StringBuilder(); + + for (Node node : list) { + String string = getContentAsStringValue(node); - return (element != null) ? element.getTextTrim() : null; - } - - // add to me content from another element - // analagous to the addAll(collection) methods in Java 2 collections - public void appendAttributes(Element element) { - for (int i = 0, size = element.attributeCount(); i < size; i++) { - Attribute attribute = element.attribute(i); - - if (attribute.supportsParent()) { - addAttribute(attribute.getQName(), attribute.getValue()); - } else { - add(attribute); - } - } - } - - /** - *

- * This returns a deep clone of this element. The new element is detached - * from its parent, and getParent() on the clone will return null. - *

- * - * @return the clone of this element - */ + if (string.length() > 0) { + if (USE_STRINGVALUE_SEPARATOR) { + if (buffer.length() > 0) { + buffer.append(' '); + } + } + + buffer.append(string); + } + } + + return buffer.toString(); + } + } + + return ""; + } + + /** + * Puts all Text nodes in the full depth of the sub-tree + * underneath this Node, including attribute nodes, into a + * "normal" form where only structure (e.g., elements, comments, processing + * instructions, CDATA sections, and entity references) separates + * Text nodes, i.e., there are neither adjacent + * Text nodes nor empty Text nodes. This can + * be used to ensure that the DOM view of a document is the same as if it + * were saved and re-loaded, and is useful when operations (such as XPointer + * lookups) that depend on a particular document tree structure are to be + * used.In cases where the document contains CDATASections, + * the normalize operation alone may not be sufficient, since XPointers do + * not differentiate between Text nodes and + * CDATASection nodes. + * + * @since DOM Level 2 + */ + public void normalize() { + List content = contentList(); + + Text previousText = null; + + int i = 0; + + while (i < content.size()) { + Node node = content.get(i); + + if (node instanceof Text) { + Text text = (Text) node; + + if (previousText != null) { + previousText.appendText(text.getText()); + + remove(text); + } else { + String value = text.getText(); + + // only remove empty Text nodes, not whitespace nodes + // if ( value == null || value.trim().length() <= 0 ) { + if ((value == null) || (value.length() <= 0)) { + remove(text); + } else { + previousText = text; + + i++; + } + } + } else { + if (node instanceof Element) { + Element element = (Element) node; + + element.normalize(); + } + + previousText = null; + + i++; + } + } + } + + public String elementText(String name) { + Element element = element(name); + + return (element != null) ? element.getText() : null; + } + + public String elementText(QName qName) { + Element element = element(qName); + + return (element != null) ? element.getText() : null; + } + + public String elementTextTrim(String name) { + Element element = element(name); + + return (element != null) ? element.getTextTrim() : null; + } + + public String elementTextTrim(QName qName) { + Element element = element(qName); + + return (element != null) ? element.getTextTrim() : null; + } + + // add to me content from another element + // analagous to the addAll(collection) methods in Java 2 collections + public void appendAttributes(Element element) { + for (int i = 0, size = element.attributeCount(); i < size; i++) { + Attribute attribute = element.attribute(i); + + if (attribute.supportsParent()) { + addAttribute(attribute.getQName(), attribute.getValue()); + } else { + add(attribute); + } + } + } + + /** + *

+ * This returns a deep clone of this element. The new element is detached + * from its parent, and getParent() on the clone will return null. + *

+ * + * @return the clone of this element + */ /* * public Object clone() { Element clone = createElement(getQName()); * clone.appendAttributes(this); clone.appendContent(this); return clone; } */ - public Element createCopy() { - Element clone = createElement(getQName()); - - clone.appendAttributes(this); - - clone.appendContent(this); - - return clone; - } - - public Element createCopy(String name) { - Element clone = createElement(name); - - clone.appendAttributes(this); - - clone.appendContent(this); - - return clone; - } - - public Element createCopy(QName qName) { - Element clone = createElement(qName); - - clone.appendAttributes(this); - - clone.appendContent(this); - - return clone; - } - - public QName getQName(String qualifiedName) { - String prefix = ""; - - String localName = qualifiedName; - - int index = qualifiedName.indexOf(":"); - - if (index > 0) { - prefix = qualifiedName.substring(0, index); - - localName = qualifiedName.substring(index + 1); - } - - Namespace namespace = getNamespaceForPrefix(prefix); - - if (namespace != null) { - return getDocumentFactory().createQName(localName, namespace); - } else { - return getDocumentFactory().createQName(localName); - } - } - - public Namespace getNamespaceForPrefix(String prefix) { - if (prefix == null) { - prefix = ""; - } - - if (prefix.equals(getNamespacePrefix())) { - return getNamespace(); - } else if (prefix.equals("xml")) { - return Namespace.XML_NAMESPACE; - } else { - List list = contentList(); - - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; + public Element createCopy() { + Element clone = createElement(getQName()); - if (prefix.equals(namespace.getPrefix())) { - return namespace; - } - } - } - } + clone.appendAttributes(this); - Element parent = getParent(); + clone.appendContent(this); - if (parent != null) { - Namespace answer = parent.getNamespaceForPrefix(prefix); + return clone; + } - if (answer != null) { - return answer; - } - } + public Element createCopy(String name) { + Element clone = createElement(name); - if ((prefix == null) || (prefix.length() <= 0)) { - return Namespace.NO_NAMESPACE; - } + clone.appendAttributes(this); - return null; - } + clone.appendContent(this); - public Namespace getNamespaceForURI(String uri) { - if ((uri == null) || (uri.length() <= 0)) { - return Namespace.NO_NAMESPACE; - } else if (uri.equals(getNamespaceURI())) { - return getNamespace(); - } else { - List list = contentList(); + return clone; + } - int size = list.size(); + public Element createCopy(QName qName) { + Element clone = createElement(qName); - for (int i = 0; i < size; i++) { - Object object = list.get(i); + clone.appendAttributes(this); - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; + clone.appendContent(this); - if (uri.equals(namespace.getURI())) { - return namespace; - } - } - } + return clone; + } - return null; - } - } + public QName getQName(String qualifiedName) { + String prefix = ""; - public List getNamespacesForURI(String uri) { - BackedList answer = createResultList(); + String localName = qualifiedName; - // if (getNamespaceURI().equals(uri)) { - // - // answer.addLocal(getNamespace()); - // - // } - List list = contentList(); + int index = qualifiedName.indexOf(":"); - int size = list.size(); + if (index > 0) { + prefix = qualifiedName.substring(0, index); - for (int i = 0; i < size; i++) { - Object object = list.get(i); + localName = qualifiedName.substring(index + 1); + } - if ((object instanceof Namespace) - && ((Namespace) object).getURI().equals(uri)) { - answer.addLocal(object); - } - } + Namespace namespace = getNamespaceForPrefix(prefix); - return answer; - } + if (namespace != null) { + return getDocumentFactory().createQName(localName, namespace); + } else { + return getDocumentFactory().createQName(localName); + } + } - public List declaredNamespaces() { - BackedList answer = createResultList(); + public Namespace getNamespaceForPrefix(String prefix) { + if (prefix == null) { + prefix = ""; + } - // if (getNamespaceURI().length() > 0) { - // - // answer.addLocal(getNamespace()); - // - // } - // - List list = contentList(); + if (prefix.equals(getNamespacePrefix())) { + return getNamespace(); + } else if (prefix.equals("xml")) { + return Namespace.XML_NAMESPACE; + } else { + for (Node node : contentList()) { + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; - int size = list.size(); + if (prefix.equals(namespace.getPrefix())) { + return namespace; + } + } + } + } - for (int i = 0; i < size; i++) { - Object object = list.get(i); + Element parent = getParent(); - if (object instanceof Namespace) { - answer.addLocal(object); - } - } + if (parent != null) { + Namespace answer = parent.getNamespaceForPrefix(prefix); - return answer; - } + if (answer != null) { + return answer; + } + } - public List additionalNamespaces() { - List list = contentList(); + if ((prefix.length() == 0)) { + return Namespace.NO_NAMESPACE; + } - int size = list.size(); + return null; + } - BackedList answer = createResultList(); + public Namespace getNamespaceForURI(String uri) { + if ((uri == null) || (uri.length() <= 0)) { + return Namespace.NO_NAMESPACE; + } else if (uri.equals(getNamespaceURI())) { + return getNamespace(); + } else { + for (Node node : contentList()) { + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; - for (int i = 0; i < size; i++) { - Object object = list.get(i); + if (uri.equals(namespace.getURI())) { + return namespace; + } + } + } - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; + return null; + } + } - if (!namespace.equals(getNamespace())) { - answer.addLocal(namespace); - } - } - } + public List getNamespacesForURI(String uri) { + BackedList answer = createResultList(); - return answer; - } + for (Node node : contentList()) { + if ((node instanceof Namespace) + && ((Namespace) node).getURI().equals(uri)) { + answer.addLocal((Namespace) node); + } + } - public List additionalNamespaces(String defaultNamespaceURI) { - List list = contentList(); - - BackedList answer = createResultList(); - - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; - - if (!defaultNamespaceURI.equals(namespace.getURI())) { - answer.addLocal(namespace); - } - } - } - - return answer; - } - - // Implementation helper methods - // ------------------------------------------------------------------------- - - /** - * Ensures that the list of attributes has the given size - * - * @param minCapacity - * DOCUMENT ME! - */ - public void ensureAttributesCapacity(int minCapacity) { - if (minCapacity > 1) { - List list = attributeList(); - - if (list instanceof ArrayList) { - ArrayList arrayList = (ArrayList) list; - - arrayList.ensureCapacity(minCapacity); - } - } - } - - // Implementation methods - // ------------------------------------------------------------------------- - protected Element createElement(String name) { - return getDocumentFactory().createElement(name); - } - - protected Element createElement(QName qName) { - return getDocumentFactory().createElement(qName); - } - - protected void addNode(Node node) { - if (node.getParent() != null) { - // XXX: could clone here - String message = "The Node already has an existing parent of \"" - + node.getParent().getQualifiedName() + "\""; - - throw new IllegalAddException(this, node, message); - } - - addNewNode(node); - } - - protected void addNode(int index, Node node) { - if (node.getParent() != null) { - // XXX: could clone here - String message = "The Node already has an existing parent of \"" - + node.getParent().getQualifiedName() + "\""; - - throw new IllegalAddException(this, node, message); - } - - addNewNode(index, node); - } - - /** - * Like addNode() but does not require a parent check - * - * @param node - * DOCUMENT ME! - */ - protected void addNewNode(Node node) { - contentList().add(node); - - childAdded(node); - } - - protected void addNewNode(int index, Node node) { - contentList().add(index, node); - - childAdded(node); - } - - protected boolean removeNode(Node node) { - boolean answer = contentList().remove(node); - - if (answer) { - childRemoved(node); - } - - return answer; - } - - /** - * Called when a new child node is added to create any parent relationships - * - * @param node - * DOCUMENT ME! - */ - protected void childAdded(Node node) { - if (node != null) { - node.setParent(this); - } - } - - protected void childRemoved(Node node) { - if (node != null) { - node.setParent(null); - - node.setDocument(null); - } - } - - /** - * DOCUMENT ME! - * - * @return the internal List used to store attributes or creates one if one - * is not available - */ - protected abstract List attributeList(); - - /** - * DOCUMENT ME! - * - * @param attributeCount - * DOCUMENT ME! - * - * @return the internal List used to store attributes or creates one with - * the specified size if one is not available - */ - protected abstract List attributeList(int attributeCount); - - protected DocumentFactory getDocumentFactory() { - QName qName = getQName(); - - // QName might be null as we might not have been constructed yet - if (qName != null) { - DocumentFactory factory = qName.getDocumentFactory(); - - if (factory != null) { - return factory; - } - } - - return DOCUMENT_FACTORY; - } - - /** - * A Factory Method pattern which creates a List implementation used to - * store attributes - * - * @return DOCUMENT ME! - */ - protected List createAttributeList() { - return createAttributeList(DEFAULT_CONTENT_LIST_SIZE); - } - - /** - * A Factory Method pattern which creates a List implementation used to - * store attributes - * - * @param size - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - protected List createAttributeList(int size) { - return new ArrayList(size); - } + return answer; + } - protected Iterator createSingleIterator(Object result) { - return new SingleIterator(result); - } + public List declaredNamespaces() { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + if (node instanceof Namespace) { + answer.addLocal((Namespace) node); + } + } + + return answer; + } + + public List additionalNamespaces() { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; + + if (!namespace.equals(getNamespace())) { + answer.addLocal(namespace); + } + } + } + + return answer; + } + + public List additionalNamespaces(String defaultNamespaceURI) { + BackedList answer = createResultList(); + + for (Node node : contentList()) { + + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; + + if (!defaultNamespaceURI.equals(namespace.getURI())) { + answer.addLocal(namespace); + } + } + } + + return answer; + } + + // Implementation helper methods + // ------------------------------------------------------------------------- + + /** + * Ensures that the list of attributes has the given size + * + * @param minCapacity DOCUMENT ME! + */ + public void ensureAttributesCapacity(int minCapacity) { + if (minCapacity > 1) { + List list = attributeList(); + + if (list instanceof ArrayList) { + ArrayList arrayList = (ArrayList) list; + + arrayList.ensureCapacity(minCapacity); + } + } + } + + // Implementation methods + // ------------------------------------------------------------------------- + protected Element createElement(String name) { + return getDocumentFactory().createElement(name); + } + + protected Element createElement(QName qName) { + return getDocumentFactory().createElement(qName); + } + + protected void addNode(Node node) { + if (node.getParent() != null) { + // XXX: could clone here + String message = "The Node already has an existing parent of \"" + + node.getParent().getQualifiedName() + "\""; + + throw new IllegalAddException(this, node, message); + } + + addNewNode(node); + } + + protected void addNode(int index, Node node) { + if (node.getParent() != null) { + // XXX: could clone here + String message = "The Node already has an existing parent of \"" + + node.getParent().getQualifiedName() + "\""; + + throw new IllegalAddException(this, node, message); + } + + addNewNode(index, node); + } + + /** + * Like addNode() but does not require a parent check + * + * @param node DOCUMENT ME! + */ + protected void addNewNode(Node node) { + contentList().add(node); + + childAdded(node); + } + + protected void addNewNode(int index, Node node) { + contentList().add(index, node); + + childAdded(node); + } + + protected boolean removeNode(Node node) { + boolean answer = contentList().remove(node); + + if (answer) { + childRemoved(node); + } + + return answer; + } + + /** + * Called when a new child node is added to create any parent relationships + * + * @param node DOCUMENT ME! + */ + protected void childAdded(Node node) { + if (node != null) { + node.setParent(this); + } + } + + protected void childRemoved(Node node) { + if (node != null) { + node.setParent(null); + + node.setDocument(null); + } + } + + /** + * DOCUMENT ME! + * + * @return the internal List used to store attributes or creates one if one + * is not available + */ + protected abstract List attributeList(); + + /** + * DOCUMENT ME! + * + * @param attributeCount DOCUMENT ME! + * @return the internal List used to store attributes or creates one with + * the specified size if one is not available + */ + protected abstract List attributeList(int attributeCount); + + protected DocumentFactory getDocumentFactory() { + QName qName = getQName(); + + // QName might be null as we might not have been constructed yet + if (qName != null) { + DocumentFactory factory = qName.getDocumentFactory(); + + if (factory != null) { + return factory; + } + } + + return DOCUMENT_FACTORY; + } + + /** + * A Factory Method pattern which creates a List implementation used to + * store attributes + * + * @return DOCUMENT ME! + */ + protected List createAttributeList() { + return createAttributeList(DEFAULT_CONTENT_LIST_SIZE); + } + + /** + * A Factory Method pattern which creates a List implementation used to + * store attributes + * + * @param size DOCUMENT ME! + * @return DOCUMENT ME! + */ + protected List createAttributeList(int size) { + return new ArrayList(size); + } + + protected Iterator createSingleIterator(T result) { + return new SingleIterator(result); + } } /* diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractEntity.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractEntity.java index 0052895a0..3bbefcd9f 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractEntity.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractEntity.java @@ -21,7 +21,7 @@ import org.dom4j.Visitor; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.15 $ */ public abstract class AbstractEntity extends AbstractNode implements Entity { public AbstractEntity() { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractNode.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractNode.java index 7bea8502e..3957c297c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractNode.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractNode.java @@ -7,19 +7,14 @@ package org.dom4j.tree; +import org.dom4j.*; +import org.dom4j.rule.Pattern; + import java.io.IOException; import java.io.Serializable; import java.io.Writer; import java.util.List; -import org.dom4j.Document; -import org.dom4j.DocumentFactory; -import org.dom4j.Element; -import org.dom4j.Node; -import org.dom4j.NodeFilter; -import org.dom4j.XPath; -import org.dom4j.rule.Pattern; - /** *

* AbstractNode is an abstract base class for tree implementors @@ -27,7 +22,7 @@ import org.dom4j.rule.Pattern; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.31 $ */ public abstract class AbstractNode implements Node, Cloneable, Serializable { protected static final String[] NODE_TYPE_NAMES = {"Node", "Element", @@ -160,18 +155,18 @@ public abstract class AbstractNode implements Node, Cloneable, Serializable { return xpath.evaluate(this); } - public List selectNodes(String xpathExpression) { + public List selectNodes(String xpathExpression) { XPath xpath = createXPath(xpathExpression); return xpath.selectNodes(this); } - public List selectNodes(String xpathExpression, + public List selectNodes(String xpathExpression, String comparisonXPathExpression) { return selectNodes(xpathExpression, comparisonXPathExpression, false); } - public List selectNodes(String xpathExpression, + public List selectNodes(String xpathExpression, String comparisonXPathExpression, boolean removeDuplicates) { XPath xpath = createXPath(xpathExpression); XPath sortBy = createXPath(comparisonXPathExpression); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractProcessingInstruction.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractProcessingInstruction.java index 3c8672659..fa56897f0 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractProcessingInstruction.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractProcessingInstruction.java @@ -7,17 +7,16 @@ package org.dom4j.tree; +import org.dom4j.Element; +import org.dom4j.ProcessingInstruction; +import org.dom4j.Visitor; + import java.io.IOException; import java.io.Writer; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.StringTokenizer; -import org.dom4j.Element; -import org.dom4j.ProcessingInstruction; -import org.dom4j.Visitor; - /** *

* AbstractProcessingInstruction is an abstract base class for @@ -25,7 +24,7 @@ import org.dom4j.Visitor; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.17 $ */ public abstract class AbstractProcessingInstruction extends AbstractNode implements ProcessingInstruction { @@ -78,7 +77,7 @@ public abstract class AbstractProcessingInstruction extends AbstractNode + "cannot be modified"); } - public void setValues(Map data) { + public void setValues(Map data) { throw new UnsupportedOperationException("This PI is read-only and " + "cannot be modified"); } @@ -107,13 +106,12 @@ public abstract class AbstractProcessingInstruction extends AbstractNode * * @return DOCUMENT ME! */ - protected String toString(Map values) { - StringBuffer buffer = new StringBuffer(); + protected String toString(Map values) { + StringBuilder buffer = new StringBuilder(); - for (Iterator iter = values.entrySet().iterator(); iter.hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); - String name = (String) entry.getKey(); - String value = (String) entry.getValue(); + for (Map.Entry entry : values.entrySet()) { + String name = entry.getKey(); + String value = entry.getValue(); buffer.append(name); buffer.append("=\""); @@ -137,8 +135,8 @@ public abstract class AbstractProcessingInstruction extends AbstractNode * * @return DOCUMENT ME! */ - protected Map parseValues(String text) { - Map data = new HashMap(); + protected Map parseValues(String text) { + Map data = new HashMap(); StringTokenizer s = new StringTokenizer(text, " =\'\"", true); @@ -156,7 +154,7 @@ public abstract class AbstractProcessingInstruction extends AbstractNode private String getName(StringTokenizer tokenizer) { String token = tokenizer.nextToken(); - StringBuffer name = new StringBuffer(token); + StringBuilder name = new StringBuilder(token); while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); @@ -173,7 +171,7 @@ public abstract class AbstractProcessingInstruction extends AbstractNode private String getValue(StringTokenizer tokenizer) { String token = tokenizer.nextToken(); - StringBuffer value = new StringBuffer(); + StringBuilder value = new StringBuilder(); /* get the quote */ while (tokenizer.hasMoreTokens() && !token.equals("\'") diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractText.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractText.java index ab35182fb..e40a7f12e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractText.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/AbstractText.java @@ -19,7 +19,7 @@ import org.dom4j.Visitor; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public abstract class AbstractText extends AbstractCharacterData implements org.dom4j.Text { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/BackedList.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/BackedList.java index 018993a02..5ea0c131b 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/BackedList.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/BackedList.java @@ -7,14 +7,13 @@ package org.dom4j.tree; +import org.dom4j.Node; + import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; -import org.dom4j.IllegalAddException; -import org.dom4j.Node; - /** *

* BackedList represents a list of content of a {@link @@ -23,39 +22,41 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.14 $ */ -public class BackedList extends ArrayList { +public class BackedList extends ArrayList { /** The content of the Branch which is modified if I am modified */ - private List branchContent; + private List branchContent; /** The AbstractBranch instance which owns the content */ private AbstractBranch branch; - public BackedList(AbstractBranch branch, List branchContent) { + public BackedList(AbstractBranch branch, List branchContent) { this(branch, branchContent, branchContent.size()); } - public BackedList(AbstractBranch branch, List branchContent, int capacity) { + public BackedList(AbstractBranch branch, List branchContent, int capacity) { super(capacity); this.branch = branch; this.branchContent = branchContent; } - public BackedList(AbstractBranch branch, List branchContent, - List initialContent) { + public BackedList(AbstractBranch branch, List branchContent, + List initialContent) { super(initialContent); this.branch = branch; this.branchContent = branchContent; } - public boolean add(Object object) { - branch.addNode(asNode(object)); + @Override + public boolean add(T node) { + branch.addNode(node); - return super.add(object); + return super.add(node); } - public void add(int index, Object object) { + @Override + public void add(int index, T node) { int size = size(); if (index < 0) { @@ -76,11 +77,12 @@ public class BackedList extends ArrayList { realIndex = branchContent.indexOf(get(size - 1)) + 1; } - branch.addNode(realIndex, asNode(object)); - super.add(index, object); + branch.addNode(realIndex, node); + super.add(index, node); } - public Object set(int index, Object object) { + @Override + public T set(int index, T node) { int realIndex = branchContent.indexOf(get(index)); if (realIndex < 0) { @@ -88,63 +90,69 @@ public class BackedList extends ArrayList { } if (realIndex < branchContent.size()) { - branch.removeNode(asNode(get(index))); - branch.addNode(realIndex, asNode(object)); + branch.removeNode(get(index)); + branch.addNode(realIndex, node); } else { - branch.removeNode(asNode(get(index))); - branch.addNode(asNode(object)); + branch.removeNode(get(index)); + branch.addNode(node); } - branch.childAdded(asNode(object)); + branch.childAdded(node); - return super.set(index, object); + return super.set(index, node); } + @Override public boolean remove(Object object) { - branch.removeNode(asNode(object)); + if (object instanceof Node) { + branch.removeNode((Node) object); + } return super.remove(object); } - public Object remove(int index) { - Object object = super.remove(index); + @Override + public T remove(int index) { + T node = super.remove(index); - if (object != null) { - branch.removeNode(asNode(object)); + if (node != null) { + branch.removeNode(node); } - return object; + return node; } - public boolean addAll(Collection collection) { + @Override + public boolean addAll(Collection collection) { ensureCapacity(size() + collection.size()); int count = size(); - for (Iterator iter = collection.iterator(); iter.hasNext(); count--) { + for (Iterator iter = collection.iterator(); iter.hasNext(); count--) { add(iter.next()); } return count != 0; } - public boolean addAll(int index, Collection collection) { + @Override + public boolean addAll(int index, Collection collection) { ensureCapacity(size() + collection.size()); int count = size(); - for (Iterator iter = collection.iterator(); iter.hasNext(); count--) { + for (Iterator iter = collection.iterator(); iter.hasNext(); count--) { add(index++, iter.next()); } return count != 0; } + @Override public void clear() { - for (Iterator iter = iterator(); iter.hasNext();) { - Object object = iter.next(); - branchContent.remove(object); - branch.childRemoved(asNode(object)); + for (Node node : this) { + branchContent.remove(node); + branch.childRemoved(node); } super.clear(); @@ -154,20 +162,11 @@ public class BackedList extends ArrayList { * Performs a local addition which is not forward through to the Branch or * backing list * - * @param object + * @param node * DOCUMENT ME! */ - public void addLocal(Object object) { - super.add(object); - } - - protected Node asNode(Object object) { - if (object instanceof Node) { - return (Node) object; - } else { - throw new IllegalAddException("This list must contain instances " - + "of Node. Invalid type: " + object); - } + public void addLocal(T node) { + super.add(node); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/BaseElement.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/BaseElement.java index b4df1ecbb..8d8577801 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/BaseElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/BaseElement.java @@ -7,13 +7,9 @@ package org.dom4j.tree; -import java.util.List; +import org.dom4j.*; -import org.dom4j.Branch; -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; +import java.util.List; /** *

@@ -22,7 +18,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class BaseElement extends AbstractElement { /** The QName for this element */ @@ -37,10 +33,10 @@ public class BaseElement extends AbstractElement { private Branch parentBranch; /** List of content nodes. */ - protected List content; + protected List content; /** list of attributes */ - protected List attributes; + protected List attributes; public BaseElement(String name) { this.qname = getDocumentFactory().createQName(name); @@ -104,25 +100,25 @@ public class BaseElement extends AbstractElement { contentList().clear(); } - public void setContent(List content) { + public void setContent(List content) { this.content = content; if (content instanceof ContentListFacade) { - this.content = ((ContentListFacade) content).getBackingList(); + this.content = ((ContentListFacade) content).getBackingList(); } } - public void setAttributes(List attributes) { + public void setAttributes(List attributes) { this.attributes = attributes; if (attributes instanceof ContentListFacade) { - this.attributes = ((ContentListFacade) attributes).getBackingList(); + this.attributes = ((ContentListFacade) attributes).getBackingList(); } } // Implementation methods // ------------------------------------------------------------------------- - protected List contentList() { + protected List contentList() { if (content == null) { content = createContentList(); } @@ -130,7 +126,7 @@ public class BaseElement extends AbstractElement { return content; } - protected List attributeList() { + protected List attributeList() { if (attributes == null) { attributes = createAttributeList(); } @@ -138,7 +134,7 @@ public class BaseElement extends AbstractElement { return attributes; } - protected List attributeList(int size) { + protected List attributeList(int size) { if (attributes == null) { attributes = createAttributeList(size); } @@ -146,7 +142,7 @@ public class BaseElement extends AbstractElement { return attributes; } - protected void setAttributeList(List attributeList) { + protected void setAttributeList(List attributeList) { this.attributes = attributeList; } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/ConcurrentReaderHashMap.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/ConcurrentReaderHashMap.java deleted file mode 100644 index 12dd76ce6..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/ConcurrentReaderHashMap.java +++ /dev/null @@ -1,1284 +0,0 @@ -/* - File: ConcurrentReaderHashMap - - Written by Doug Lea. Adapted and released, under explicit - permission, from JDK1.2 HashMap.java and Hashtable.java which - carries the following copyright: - - * Copyright 1997 by Sun Microsystems, Inc., - * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. - * All rights reserved. - * - * This software is the confidential and proprietary information - * of Sun Microsystems, Inc. ("Confidential Information"). You - * shall not disclose such Confidential Information and shall use - * it only in accordance with the terms of the license agreement - * you entered into with Sun. - - History: - Date Who What - 28oct1999 dl Created - 14dec1999 dl jmm snapshot - 19apr2000 dl use barrierLock - 12jan2001 dl public release - 17nov2001 dl Minor tunings - 20may2002 dl BarrierLock can now be serialized. - 09dec2002 dl Fix interference checks. - */ - -package org.dom4j.tree; - -import java.io.IOException; -import java.io.Serializable; -import java.util.AbstractCollection; -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * A version of Hashtable that supports mostly-concurrent reading, but exclusive - * writing. Because reads are not limited to periods without writes, a - * concurrent reader policy is weaker than a classic reader/writer policy, but - * is generally faster and allows more concurrency. This class is a good choice - * especially for tables that are mainly created by one thread during the - * start-up phase of a program, and from then on, are mainly read (with perhaps - * occasional additions or removals) in many threads. If you also need - * concurrency among writes, consider instead using ConcurrentHashMap. - *

- * - * Successful retrievals using get(key) and containsKey(key) usually run without - * locking. Unsuccessful ones (i.e., when the key is not present) do involve - * brief synchronization (locking). Also, the size and isEmpty methods are - * always synchronized. - * - *

- * Because retrieval operations can ordinarily overlap with writing operations - * (i.e., put, remove, and their derivatives), retrievals can only be guaranteed - * to return the results of the most recently completed operations - * holding upon their onset. Retrieval operations may or may not return results - * reflecting in-progress writing operations. However, the retrieval operations - * do always return consistent results -- either those holding before any single - * modification or after it, but never a nonsense result. For aggregate - * operations such as putAll and clear, concurrent reads may reflect insertion - * or removal of only some entries. In those rare contexts in which you use a - * hash table to synchronize operations across threads (for example, to prevent - * reads until after clears), you should either encase operations in - * synchronized blocks, or instead use java.util.Hashtable. - * - *

- * - * This class also supports optional guaranteed exclusive reads, simply by - * surrounding a call within a synchronized block, as in
- * ConcurrentReaderHashMap t; ... Object v;
- * synchronized(t) { v = t.get(k); }

- * - * But this is not usually necessary in practice. For example, it is generally - * inefficient to write: - * - *

- * 
- *  
- *     ConcurrentReaderHashMap t; ...            // Inefficient version
- *     Object key; ...
- *     Object value; ...
- *     synchronized(t) { 
- *       if (!t.containsKey(key))
- *         t.put(key, value);
- *         // other code if not previously present
- *       }
- *       else {
- *         // other code if it was previously present
- *       }
- *     }
- *  
- *  
- * 
- * - * Instead, if the values are intended to be the same in each case, just take - * advantage of the fact that put returns null if the key was not previously - * present: - * - *
- * 
- *  
- *     ConcurrentReaderHashMap t; ...                // Use this instead
- *     Object key; ...
- *     Object value; ...
- *     Object oldValue = t.put(key, value);
- *     if (oldValue == null) {
- *       // other code if not previously present
- *     }
- *     else {
- *       // other code if it was previously present
- *     }
- *  
- *  
- * 
- * - *

- * - * Iterators and Enumerations (i.e., those returned by keySet().iterator(), - * entrySet().iterator(), values().iterator(), keys(), and elements()) return - * elements reflecting the state of the hash table at some point at or since the - * creation of the iterator/enumeration. They will return at most one instance - * of each element (via next()/nextElement()), but might or might not reflect - * puts and removes that have been processed since they were created. They do - * not throw ConcurrentModificationException. However, these - * iterators are designed to be used by only one thread at a time. Sharing an - * iterator across multiple threads may lead to unpredictable results if the - * table is being concurrently modified. Again, you can ensure interference-free - * iteration by enclosing the iteration in a synchronized block. - *

- * - * This class may be used as a direct replacement for any use of - * java.util.Hashtable that does not depend on readers being blocked during - * updates. Like Hashtable but unlike java.util.HashMap, this class does NOT - * allow null to be used as a key or value. This class is also - * typically faster than ConcurrentHashMap when there is usually only one thread - * updating the table, but possibly many retrieving values from it. - *

- * - * Implementation note: A slightly faster implementation of this class will be - * possible once planned Java Memory Model revisions are in place. - * - *

[ - * Introduction to this package. ] - * - */ - -class ConcurrentReaderHashMap extends AbstractMap implements Map, Cloneable, - Serializable { - - /* - * The basic strategy is an optimistic-style scheme based on the guarantee - * that the hash table and its lists are always kept in a consistent enough - * state to be read without locking: - * - * Read operations first proceed without locking, by traversing the - * apparently correct list of the apparently correct bin. If an entry is - * found, but not invalidated (value field null), it is returned. If not - * found, operations must recheck (after a memory barrier) to make sure they - * are using both the right list and the right table (which can change under - * resizes). If invalidated, reads must acquire main update lock to wait out - * the update, and then re-traverse. - * - * All list additions are at the front of each bin, making it easy to check - * changes, and also fast to traverse. Entry next pointers are never - * assigned. Remove() builds new nodes when necessary to preserve this. - * - * Remove() (also clear()) invalidates removed nodes to alert read - * operations that they must wait out the full modifications. - * - */ - - /** A Serializable class for barrier lock * */ - protected static class BarrierLock implements java.io.Serializable { - } - - /** - * Lock used only for its memory effects. - */ - protected final BarrierLock barrierLock = new BarrierLock(); - - /** - * field written to only to guarantee lock ordering. - */ - - protected transient Object lastWrite; - - /** - * Force a memory synchronization that will cause all readers to see table. - * Call only when already holding main synch lock. - */ - protected final void recordModification(Object x) { - synchronized (barrierLock) { - lastWrite = x; - } - } - - /** - * Get ref to table; the reference and the cells it accesses will be at - * least as fresh as from last use of barrierLock - */ - protected final Entry[] getTableForReading() { - synchronized (barrierLock) { - return table; - } - } - - /** - * The default initial number of table slots for this table (32). Used when - * not otherwise specified in constructor. - */ - public static int DEFAULT_INITIAL_CAPACITY = 32; - - /** - * The minimum capacity, used if a lower value is implicitly specified by - * either of the constructors with arguments. MUST be a power of two. - */ - private static final int MINIMUM_CAPACITY = 4; - - /** - * The maximum capacity, used if a higher value is implicitly specified by - * either of the constructors with arguments. MUST be a power of two <= 1 < - * <30. - */ - private static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The default load factor for this table (1.0). Used when not otherwise - * specified in constructor. - */ - - public static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The hash table data. - */ - protected transient Entry[] table; - - /** - * The total number of mappings in the hash table. - */ - protected transient int count; - - /** - * The table is rehashed when its size exceeds this threshold. (The value of - * this field is always (int)(capacity * loadFactor).) - * - * @serial - */ - protected int threshold; - - /** - * The load factor for the hash table. - * - * @serial - */ - protected float loadFactor; - - /** - * Returns the appropriate capacity (power of two) for the specified initial - * capacity argument. - */ - private int p2capacity(int initialCapacity) { - int cap = initialCapacity; - - // Compute the appropriate capacity - int result; - if (cap > MAXIMUM_CAPACITY || cap < 0) { - result = MAXIMUM_CAPACITY; - } else { - result = MINIMUM_CAPACITY; - while (result < cap) - result <<= 1; - } - return result; - } - - /** - * Return hash code for Object x. Since we are using power-of-two tables, it - * is worth the effort to improve hashcode via the same multiplicative - * scheme as used in IdentityHashMap. - */ - private static int hash(Object x) { - int h = x.hashCode(); - // Multiply by 127 (quickly, via shifts), and mix in some high - // bits to help guard against bunching of codes that are - // consecutive or equally spaced. - return ((h << 7) - h + (h >>> 9) + (h >>> 17)); - } - - /** - * Check for equality of non-null references x and y. - */ - protected boolean eq(Object x, Object y) { - return x == y || x.equals(y); - } - - /** - * Constructs a new, empty map with the specified initial capacity and the - * specified load factor. - * - * @param initialCapacity - * the initial capacity The actual initial capacity is rounded to - * the nearest power of two. - * @param loadFactor - * the load factor of the ConcurrentReaderHashMap - * @throws IllegalArgumentException - * if the initial maximum number of elements is less than zero, - * or if the load factor is nonpositive. - */ - - public ConcurrentReaderHashMap(int initialCapacity, float loadFactor) { - if (loadFactor <= 0) - throw new IllegalArgumentException("Illegal Load factor: " - + loadFactor); - this.loadFactor = loadFactor; - - int cap = p2capacity(initialCapacity); - - table = new Entry[cap]; - threshold = (int) (cap * loadFactor); - } - - /** - * Constructs a new, empty map with the specified initial capacity and - * default load factor. - * - * @param initialCapacity - * the initial capacity of the ConcurrentReaderHashMap. - * @throws IllegalArgumentException - * if the initial maximum number of elements is less than zero. - */ - - public ConcurrentReaderHashMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs a new, empty map with a default initial capacity and load - * factor. - */ - - public ConcurrentReaderHashMap() { - this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs a new map with the same mappings as the given map. The map is - * created with a capacity of twice the number of mappings in the given map - * or 16 (whichever is greater), and a default load factor. - */ - - public ConcurrentReaderHashMap(Map t) { - this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1, 16), - DEFAULT_LOAD_FACTOR); - putAll(t); - } - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map. - */ - - public synchronized int size() { - return count; - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings. - */ - - public synchronized boolean isEmpty() { - return count == 0; - } - - /** - * Returns the value to which the specified key is mapped in this table. - * - * @param key - * a key in the table. - * @return the value to which the key is mapped in this table; - * null if the key is not mapped to any value in this - * table. - * @exception NullPointerException - * if the key is null. - * @see #put(Object, Object) - */ - - public Object get(Object key) { - - // throw null pointer exception if key null - int hash = hash(key); - - /* - * Start off at the apparently correct bin. If entry is found, we need - * to check after a barrier anyway. If not found, we need a barrier to - * check if we are actually in right bin. So either way, we encounter - * only one barrier unless we need to retry. And we only need to fully - * synchronize if there have been concurrent modifications. - */ - - Entry[] tab = table; - int index = hash & (tab.length - 1); - Entry first = tab[index]; - Entry e = first; - - for (;;) { - if (e == null) { - - // If key apparently not there, check to - // make sure this was a valid read - - Entry[] reread = getTableForReading(); - if (tab == reread && first == tab[index]) - return null; - else { - // Wrong list -- must restart traversal at new first - tab = reread; - e = first = tab[index = hash & (tab.length - 1)]; - } - - } - - else if (e.hash == hash && eq(key, e.key)) { - Object value = e.value; - if (value != null) - return value; - - // Entry was invalidated during deletion. But it could - // have been re-inserted, so we must retraverse. - // To avoid useless contention, get lock to wait out - // modifications - // before retraversing. - - synchronized (this) { - tab = table; - } - e = first = tab[index = hash & (tab.length - 1)]; - - } else - e = e.next; - } - } - - /** - * Tests if the specified object is a key in this table. - * - * @param key - * possible key. - * @return true if and only if the specified object is a key - * in this table, as determined by the equals method; - * false otherwise. - * @exception NullPointerException - * if the key is null. - * @see #contains(Object) - */ - - public boolean containsKey(Object key) { - return get(key) != null; - } - - /** - * Maps the specified key to the specified value - * in this table. Neither the key nor the value can be null. - *

- * - * The value can be retrieved by calling the get method with - * a key that is equal to the original key. - * - * @param key - * the table key. - * @param value - * the value. - * @return the previous value of the specified key in this table, or - * null if it did not have one. - * @exception NullPointerException - * if the key or value is null. - * @see Object#equals(Object) - * @see #get(Object) - */ - - public Object put(Object key, Object value) { - if (value == null) - throw new NullPointerException(); - - int hash = hash(key); - Entry[] tab = table; - int index = hash & (tab.length - 1); - Entry first = tab[index]; - Entry e; - - for (e = first; e != null; e = e.next) - if (e.hash == hash && eq(key, e.key)) - break; - - synchronized (this) { - if (tab == table) { - if (e == null) { - // make sure we are adding to correct list - if (first == tab[index]) { - // Add to front of list - Entry newEntry = new Entry(hash, key, value, first); - tab[index] = newEntry; - if (++count >= threshold) - rehash(); - else - recordModification(newEntry); - return null; - } - } else { - Object oldValue = e.value; - if (first == tab[index] && oldValue != null) { - e.value = value; - return oldValue; - } - } - } - - // retry if wrong list or lost race against concurrent remove - return sput(key, value, hash); - } - } - - /** - * Continuation of put(), called only when synch lock is held and - * interference has been detected. - */ - protected Object sput(Object key, Object value, int hash) { - - Entry[] tab = table; - int index = hash & (tab.length - 1); - Entry first = tab[index]; - Entry e = first; - - for (;;) { - if (e == null) { - Entry newEntry = new Entry(hash, key, value, first); - tab[index] = newEntry; - if (++count >= threshold) - rehash(); - else - recordModification(newEntry); - return null; - } else if (e.hash == hash && eq(key, e.key)) { - Object oldValue = e.value; - e.value = value; - return oldValue; - } else - e = e.next; - } - } - - /** - * Rehashes the contents of this map into a new table with a larger - * capacity. This method is called automatically when the number of keys in - * this map exceeds its capacity and load factor. - */ - protected void rehash() { - Entry[] oldTable = table; - int oldCapacity = oldTable.length; - if (oldCapacity >= MAXIMUM_CAPACITY) { - threshold = Integer.MAX_VALUE; // avoid retriggering - return; - } - - int newCapacity = oldCapacity << 1; - int mask = newCapacity - 1; - threshold = (int) (newCapacity * loadFactor); - - Entry[] newTable = new Entry[newCapacity]; - /* - * Reclassify nodes in each list to new Map. Because we are using - * power-of-two expansion, the elements from each bin must either stay - * at same index, or move to oldCapacity+index. We also eliminate - * unnecessary node creation by catching cases where old nodes can be - * reused because their next fields won't change. Statistically, at the - * default threshhold, only about one-sixth of them need cloning. (The - * nodes they replace will be garbage collectable as soon as they are no - * longer referenced by any reader thread that may be in the midst of - * traversing table right now.) - */ - - for (int i = 0; i < oldCapacity; i++) { - // We need to guarantee that any existing reads of old Map can - // proceed. So we cannot yet null out each bin. - Entry e = oldTable[i]; - - if (e != null) { - int idx = e.hash & mask; - Entry next = e.next; - - // Single node on list - if (next == null) - newTable[idx] = e; - - else { - // Reuse trailing consecutive sequence of all same bit - Entry lastRun = e; - int lastIdx = idx; - for (Entry last = next; last != null; last = last.next) { - int k = last.hash & mask; - if (k != lastIdx) { - lastIdx = k; - lastRun = last; - } - } - newTable[lastIdx] = lastRun; - - // Clone all remaining nodes - for (Entry p = e; p != lastRun; p = p.next) { - int k = p.hash & mask; - newTable[k] = new Entry(p.hash, p.key, p.value, - newTable[k]); - } - } - } - } - - table = newTable; - recordModification(newTable); - } - - /** - * Removes the key (and its corresponding value) from this table. This - * method does nothing if the key is not in the table. - * - * @param key - * the key that needs to be removed. - * @return the value to which the key had been mapped in this table, or - * null if the key did not have a mapping. - * @exception NullPointerException - * if the key is null. - */ - - public Object remove(Object key) { - /* - * Find the entry, then 1. Set value field to null, to force get() to - * retry 2. Rebuild the list without this entry. All entries following - * removed node can stay in list, but all preceeding ones need to be - * cloned. Traversals rely on this strategy to ensure that elements will - * not be repeated during iteration. - */ - - int hash = hash(key); - Entry[] tab = table; - int index = hash & (tab.length - 1); - Entry first = tab[index]; - Entry e = first; - - for (e = first; e != null; e = e.next) - if (e.hash == hash && eq(key, e.key)) - break; - - synchronized (this) { - if (tab == table) { - if (e == null) { - if (first == tab[index]) - return null; - } else { - Object oldValue = e.value; - if (first == tab[index] && oldValue != null) { - e.value = null; - count--; - - Entry head = e.next; - for (Entry p = first; p != e; p = p.next) - head = new Entry(p.hash, p.key, p.value, head); - - tab[index] = head; - recordModification(head); - return oldValue; - } - } - } - - // Wrong list or interference - return sremove(key, hash); - } - } - - /** - * Continuation of remove(), called only when synch lock is held and - * interference has been detected. - */ - - protected Object sremove(Object key, int hash) { - Entry[] tab = table; - int index = hash & (tab.length - 1); - Entry first = tab[index]; - - for (Entry e = first; e != null; e = e.next) { - if (e.hash == hash && eq(key, e.key)) { - Object oldValue = e.value; - e.value = null; - count--; - Entry head = e.next; - for (Entry p = first; p != e; p = p.next) - head = new Entry(p.hash, p.key, p.value, head); - - tab[index] = head; - recordModification(head); - return oldValue; - } - } - return null; - } - - /** - * Returns true if this map maps one or more keys to the - * specified value. Note: This method requires a full internal traversal of - * the hash table, and so is much slower than method containsKey. - * - * @param value - * value whose presence in this map is to be tested. - * @return true if this map maps one or more keys to the - * specified value. - * @exception NullPointerException - * if the value is null. - */ - - public boolean containsValue(Object value) { - if (value == null) - throw new NullPointerException(); - - Entry tab[] = getTableForReading(); - - for (int i = 0; i < tab.length; ++i) { - for (Entry e = tab[i]; e != null; e = e.next) - if (value.equals(e.value)) - return true; - } - - return false; - } - - /** - * Tests if some key maps into the specified value in this table. This - * operation is more expensive than the containsKey method. - *

- * - * Note that this method is identical in functionality to containsValue, - * (which is part of the Map interface in the collections framework). - * - * @param value - * a value to search for. - * @return true if and only if some key maps to the - * value argument in this table as determined by the - * equals method; false otherwise. - * @exception NullPointerException - * if the value is null. - * @see #containsKey(Object) - * @see #containsValue(Object) - * @see Map - */ - - public boolean contains(Object value) { - return containsValue(value); - } - - /** - * Copies all of the mappings from the specified map to this one. - * - * These mappings replace any mappings that this map had for any of the keys - * currently in the specified Map. - * - * @param t - * Mappings to be stored in this map. - */ - - public synchronized void putAll(Map t) { - int n = t.size(); - if (n == 0) - return; - - // Expand enough to hold at least n elements without resizing. - // We can only resize table by factor of two at a time. - // It is faster to rehash with fewer elements, so do it now. - while (n >= threshold) - rehash(); - - for (Iterator it = t.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - Object value = entry.getValue(); - put(key, value); - } - } - - /** - * Removes all mappings from this map. - */ - public synchronized void clear() { - Entry tab[] = table; - for (int i = 0; i < tab.length; ++i) { - - // must invalidate all to force concurrent get's to wait and then - // retry - for (Entry e = tab[i]; e != null; e = e.next) - e.value = null; - - tab[i] = null; - } - count = 0; - recordModification(tab); - } - - /** - * Returns a shallow copy of this ConcurrentReaderHashMap - * instance: the keys and values themselves are not cloned. - * - * @return a shallow copy of this map. - */ - - public synchronized Object clone() { - try { - ConcurrentReaderHashMap t = (ConcurrentReaderHashMap) super.clone(); - - t.keySet = null; - t.entrySet = null; - t.values = null; - - Entry[] tab = table; - t.table = new Entry[tab.length]; - Entry[] ttab = t.table; - - for (int i = 0; i < tab.length; ++i) { - Entry first = null; - for (Entry e = tab[i]; e != null; e = e.next) - first = new Entry(e.hash, e.key, e.value, first); - ttab[i] = first; - } - - return t; - } catch (CloneNotSupportedException e) { - // this shouldn't happen, since we are Cloneable - throw new InternalError(); - } - } - - // Views - - protected transient Set keySet = null; - - protected transient Set entrySet = null; - - protected transient Collection values = null; - - /** - * Returns a set view of the keys contained in this map. The set is backed - * by the map, so changes to the map are reflected in the set, and - * vice-versa. The set supports element removal, which removes the - * corresponding mapping from this map, via the Iterator.remove, - * Set.remove,removeAll,retainAll, and - * clear operations. It does not support the add or - * addAll operations. - * - * @return a set view of the keys contained in this map. - */ - - public Set keySet() { - Set ks = keySet; - return (ks != null) ? ks : (keySet = new KeySet()); - } - - private class KeySet extends AbstractSet { - public Iterator iterator() { - return new KeyIterator(); - } - - public int size() { - return ConcurrentReaderHashMap.this.size(); - } - - public boolean contains(Object o) { - return ConcurrentReaderHashMap.this.containsKey(o); - } - - public boolean remove(Object o) { - return ConcurrentReaderHashMap.this.remove(o) != null; - } - - public void clear() { - ConcurrentReaderHashMap.this.clear(); - } - } - - /** - * Returns a collection view of the values contained in this map. The - * collection is backed by the map, so changes to the map are reflected in - * the collection, and vice-versa. The collection supports element removal, - * which removes the corresponding mapping from this map, via the - * Iterator.remove,Collection.remove, - * removeAll,retainAll, and clear - * operations. It does not support the add or addAll - * operations. - * - * @return a collection view of the values contained in this map. - */ - - public Collection values() { - Collection vs = values; - return (vs != null) ? vs : (values = new Values()); - } - - private class Values extends AbstractCollection { - public Iterator iterator() { - return new ValueIterator(); - } - - public int size() { - return ConcurrentReaderHashMap.this.size(); - } - - public boolean contains(Object o) { - return ConcurrentReaderHashMap.this.containsValue(o); - } - - public void clear() { - ConcurrentReaderHashMap.this.clear(); - } - } - - /** - * Returns a collection view of the mappings contained in this map. Each - * element in the returned collection is a Map.Entry. The - * collection is backed by the map, so changes to the map are reflected in - * the collection, and vice-versa. The collection supports element removal, - * which removes the corresponding mapping from the map, via the - * Iterator.remove,Collection.remove, - * removeAll,retainAll, and clear - * operations. It does not support the add or addAll - * operations. - * - * @return a collection view of the mappings contained in this map. - */ - - public Set entrySet() { - Set es = entrySet; - return (es != null) ? es : (entrySet = new EntrySet()); - } - - private class EntrySet extends AbstractSet { - public Iterator iterator() { - return new HashIterator(); - } - - public boolean contains(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry entry = (Map.Entry) o; - Object v = ConcurrentReaderHashMap.this.get(entry.getKey()); - return v != null && v.equals(entry.getValue()); - } - - public boolean remove(Object o) { - if (!(o instanceof Map.Entry)) - return false; - return ConcurrentReaderHashMap.this - .findAndRemoveEntry((Map.Entry) o); - } - - public int size() { - return ConcurrentReaderHashMap.this.size(); - } - - public void clear() { - ConcurrentReaderHashMap.this.clear(); - } - } - - /** - * Helper method for entrySet.remove - */ - protected synchronized boolean findAndRemoveEntry(Map.Entry entry) { - Object key = entry.getKey(); - Object v = get(key); - if (v != null && v.equals(entry.getValue())) { - remove(key); - return true; - } else - return false; - } - - /** - * Returns an enumeration of the keys in this table. - * - * @return an enumeration of the keys in this table. - * @see Enumeration - * @see #elements() - * @see #keySet() - * @see Map - */ - public Enumeration keys() { - return new KeyIterator(); - } - - /** - * Returns an enumeration of the values in this table. Use the Enumeration - * methods on the returned object to fetch the elements sequentially. - * - * @return an enumeration of the values in this table. - * @see java.util.Enumeration - * @see #keys() - * @see #values() - * @see Map - */ - - public Enumeration elements() { - return new ValueIterator(); - } - - /** - * ConcurrentReaderHashMap collision list entry. - */ - - protected static class Entry implements Map.Entry { - - /* - * The use of volatile for value field ensures that we can detect status - * changes without synchronization. The other fields are never changed, - * and are marked as final. - */ - - protected final int hash; - - protected final Object key; - - protected final Entry next; - - protected volatile Object value; - - Entry(int hash, Object key, Object value, Entry next) { - this.hash = hash; - this.key = key; - this.next = next; - this.value = value; - } - - // Map.Entry Ops - - public Object getKey() { - return key; - } - - /** - * Get the value. Note: In an entrySet or entrySet.iterator, unless the - * set or iterator is used under synchronization of the table as a whole - * (or you can otherwise guarantee lack of concurrent modification), - * getValue might return null, reflecting the fact - * that the entry has been concurrently removed. However, there are no - * assurances that concurrent removals will be reflected using this - * method. - * - * @return the current value, or null if the entry has been detectably - * removed. - */ - public Object getValue() { - return value; - } - - /** - * Set the value of this entry. Note: In an entrySet or - * entrySet.iterator), unless the set or iterator is used under - * synchronization of the table as a whole (or you can otherwise - * guarantee lack of concurrent modification), setValue is - * not strictly guaranteed to actually replace the value field obtained - * via the get operation of the underlying hash table in - * multithreaded applications. If iterator-wide synchronization is not - * used, and any other concurrent put or remove - * operations occur, sometimes even to other entries, then - * this change is not guaranteed to be reflected in the hash table. (It - * might, or it might not. There are no assurances either way.) - * - * @param value - * the new value. - * @return the previous value, or null if entry has been detectably - * removed. - * @exception NullPointerException - * if the value is null. - * - */ - - public Object setValue(Object value) { - if (value == null) - throw new NullPointerException(); - Object oldValue = this.value; - this.value = value; - return oldValue; - } - - public boolean equals(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry e = (Map.Entry) o; - return (key.equals(e.getKey()) && value.equals(e.getValue())); - } - - public int hashCode() { - return key.hashCode() ^ value.hashCode(); - } - - public String toString() { - return key + "=" + value; - } - - } - - protected class HashIterator implements Iterator, Enumeration { - protected final Entry[] tab; // snapshot of table - - protected int index; // current slot - - protected Entry entry = null; // current node of slot - - protected Object currentKey; // key for current node - - protected Object currentValue; // value for current node - - protected Entry lastReturned = null; // last node returned by next - - protected HashIterator() { - tab = ConcurrentReaderHashMap.this.getTableForReading(); - index = tab.length - 1; - } - - public boolean hasMoreElements() { - return hasNext(); - } - - public Object nextElement() { - return next(); - } - - public boolean hasNext() { - - /* - * currentkey and currentValue are set here to ensure that next() - * returns normally if hasNext() returns true. This avoids surprises - * especially when final element is removed during traversal -- - * instead, we just ignore the removal during current traversal. - */ - - for (;;) { - if (entry != null) { - Object v = entry.value; - if (v != null) { - currentKey = entry.key; - currentValue = v; - return true; - } else - entry = entry.next; - } - - while (entry == null && index >= 0) - entry = tab[index--]; - - if (entry == null) { - currentKey = currentValue = null; - return false; - } - } - } - - protected Object returnValueOfNext() { - return entry; - } - - public Object next() { - if (currentKey == null && !hasNext()) - throw new NoSuchElementException(); - - Object result = returnValueOfNext(); - lastReturned = entry; - currentKey = currentValue = null; - entry = entry.next; - return result; - } - - public void remove() { - if (lastReturned == null) - throw new IllegalStateException(); - ConcurrentReaderHashMap.this.remove(lastReturned.key); - lastReturned = null; - } - - } - - protected class KeyIterator extends HashIterator { - protected Object returnValueOfNext() { - return currentKey; - } - } - - protected class ValueIterator extends HashIterator { - protected Object returnValueOfNext() { - return currentValue; - } - } - - /** - * Save the state of the ConcurrentReaderHashMap instance to a - * stream (i.e., serialize it). - * - * @serialData The capacity of the ConcurrentReaderHashMap (the - * length of the bucket array) is emitted (int), followed by the - * size of the ConcurrentReaderHashMap (the number of - * key-value mappings), followed by the key (Object) and value - * (Object) for each key-value mapping represented by the - * ConcurrentReaderHashMap The key-value mappings are emitted in - * no particular order. - */ - - private synchronized void writeObject(java.io.ObjectOutputStream s) - throws IOException { - // Write out the threshold, loadfactor, and any hidden stuff - s.defaultWriteObject(); - - // Write out number of buckets - s.writeInt(table.length); - - // Write out size (number of Mappings) - s.writeInt(count); - - // Write out keys and values (alternating) - for (int index = table.length - 1; index >= 0; index--) { - Entry entry = table[index]; - - while (entry != null) { - s.writeObject(entry.key); - s.writeObject(entry.value); - entry = entry.next; - } - } - } - - /** - * Reconstitute the ConcurrentReaderHashMap instance from a - * stream (i.e., deserialize it). - */ - private synchronized void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { - // Read in the threshold, loadfactor, and any hidden stuff - s.defaultReadObject(); - - // Read in number of buckets and allocate the bucket array; - int numBuckets = s.readInt(); - table = new Entry[numBuckets]; - - // Read in size (number of Mappings) - int size = s.readInt(); - - // Read the keys and values, and put the mappings in the table - for (int i = 0; i < size; i++) { - Object key = s.readObject(); - Object value = s.readObject(); - put(key, value); - } - } - - /** - * Return the number of slots in this table - */ - - public synchronized int capacity() { - return table.length; - } - - /** - * Return the load factor - */ - public float loadFactor() { - return loadFactor; - } -} diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/ContentListFacade.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/ContentListFacade.java index 4c32035ba..192ea410d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/ContentListFacade.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/ContentListFacade.java @@ -7,14 +7,14 @@ package org.dom4j.tree; +import org.dom4j.IllegalAddException; +import org.dom4j.Node; + import java.util.AbstractList; import java.util.Collection; import java.util.Iterator; import java.util.List; -import org.dom4j.IllegalAddException; -import org.dom4j.Node; - /** *

* ContentListFacade represents a facade of the content of a @@ -26,123 +26,139 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ */ -public class ContentListFacade extends AbstractList { +public class ContentListFacade extends AbstractList { /** The content of the Branch which is modified if I am modified */ - private List branchContent; + private List branchContent; /** The AbstractBranch instance which owns the content */ private AbstractBranch branch; - public ContentListFacade(AbstractBranch branch, List branchContent) { + public ContentListFacade(AbstractBranch branch, List branchContent) { this.branch = branch; this.branchContent = branchContent; } - public boolean add(Object object) { - branch.childAdded(asNode(object)); + @Override + public boolean add(T node) { + branch.childAdded(node); - return branchContent.add(object); + return branchContent.add(node); } - public void add(int index, Object object) { - branch.childAdded(asNode(object)); - branchContent.add(index, object); + @Override + public void add(int index, T node) { + branch.childAdded(node); + branchContent.add(index, node); } - public Object set(int index, Object object) { - branch.childAdded(asNode(object)); + @Override + public T set(int index, T node) { + branch.childAdded(node); - return branchContent.set(index, object); + return branchContent.set(index, node); } + @Override public boolean remove(Object object) { branch.childRemoved(asNode(object)); return branchContent.remove(object); } - public Object remove(int index) { - Object object = branchContent.remove(index); + @Override + public T remove(int index) { + T node = branchContent.remove(index); - if (object != null) { - branch.childRemoved(asNode(object)); + if (node != null) { + branch.childRemoved(node); } - return object; + return node; } - public boolean addAll(Collection collection) { + @Override + public boolean addAll(Collection collection) { int count = branchContent.size(); - for (Iterator iter = collection.iterator(); iter.hasNext(); count++) { + for (Iterator iter = collection.iterator(); iter.hasNext(); count++) { add(iter.next()); } return count == branchContent.size(); } - public boolean addAll(int index, Collection collection) { + @Override + public boolean addAll(int index, Collection collection) { int count = branchContent.size(); - for (Iterator iter = collection.iterator(); iter.hasNext(); count--) { + for (Iterator iter = collection.iterator(); iter.hasNext(); count--) { add(index++, iter.next()); } return count == branchContent.size(); } + @Override public void clear() { - for (Iterator iter = iterator(); iter.hasNext();) { - Object object = iter.next(); - branch.childRemoved(asNode(object)); + for (Node node : this) { + branch.childRemoved(node); } branchContent.clear(); } - public boolean removeAll(Collection c) { - for (Iterator iter = c.iterator(); iter.hasNext();) { - Object object = iter.next(); + @Override + public boolean removeAll(Collection c) { + for (Object object : c) { branch.childRemoved(asNode(object)); } return branchContent.removeAll(c); } + @Override public int size() { return branchContent.size(); } + @Override public boolean isEmpty() { return branchContent.isEmpty(); } + @Override public boolean contains(Object o) { return branchContent.contains(o); } + @Override public Object[] toArray() { return branchContent.toArray(); } + @Override public Object[] toArray(Object[] a) { return branchContent.toArray(a); } - public boolean containsAll(Collection c) { + @Override + public boolean containsAll(Collection c) { return branchContent.containsAll(c); } - public Object get(int index) { + @Override + public T get(int index) { return branchContent.get(index); } + @Override public int indexOf(Object o) { return branchContent.indexOf(o); } + @Override public int lastIndexOf(Object o) { return branchContent.lastIndexOf(o); } @@ -157,7 +173,7 @@ public class ContentListFacade extends AbstractList { } } - protected List getBackingList() { + protected List getBackingList() { return branchContent; } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultAttribute.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultAttribute.java index 89fe0c483..bc6678afc 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultAttribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultAttribute.java @@ -18,7 +18,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.13 $ */ public class DefaultAttribute extends FlyweightAttribute { /** The parent of this node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultCDATA.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultCDATA.java index 9b4464605..b4dc44d8e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultCDATA.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultCDATA.java @@ -17,7 +17,7 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public class DefaultCDATA extends FlyweightCDATA { /** The parent of this node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultComment.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultComment.java index ce262e632..74970c0b4 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultComment.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultComment.java @@ -17,7 +17,7 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ */ public class DefaultComment extends FlyweightComment { /** The parent of this node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocument.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocument.java index e5eb5a9d6..db199e88b 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocument.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocument.java @@ -7,20 +7,12 @@ package org.dom4j.tree; -import java.util.Collections; +import org.dom4j.*; +import org.xml.sax.EntityResolver; + import java.util.Iterator; import java.util.List; -import org.dom4j.Document; -import org.dom4j.DocumentFactory; -import org.dom4j.DocumentType; -import org.dom4j.Element; -import org.dom4j.IllegalAddException; -import org.dom4j.Node; -import org.dom4j.ProcessingInstruction; - -import org.xml.sax.EntityResolver; - /** *

* DefaultDocument is the default DOM4J default implementation of @@ -28,13 +20,9 @@ import org.xml.sax.EntityResolver; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.34 $ */ public class DefaultDocument extends AbstractDocument { - protected static final List EMPTY_LIST = Collections.EMPTY_LIST; - - protected static final Iterator EMPTY_ITERATOR = EMPTY_LIST.iterator(); - /** The name of the document */ private String name; @@ -44,7 +32,7 @@ public class DefaultDocument extends AbstractDocument { /** * Store the contents of the document as a lazily created List */ - private List content; + private List content; /** The document type for this document */ private DocumentType docType; @@ -131,32 +119,24 @@ public class DefaultDocument extends AbstractDocument { return document; } - public List processingInstructions() { - List source = contentList(); - List answer = createResultList(); - int size = source.size(); + public List processingInstructions() { + List answer = createResultList(); - for (int i = 0; i < size; i++) { - Object object = source.get(i); - - if (object instanceof ProcessingInstruction) { - answer.add(object); + for (Node node : contentList()) { + if (node instanceof ProcessingInstruction) { + answer.add((ProcessingInstruction) node); } } return answer; } - public List processingInstructions(String target) { - List source = contentList(); - List answer = createResultList(); - int size = source.size(); - - for (int i = 0; i < size; i++) { - Object object = source.get(i); + public List processingInstructions(String target) { + List answer = createResultList(); - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + for (Node node : contentList()) { + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; if (target.equals(pi.getName())) { answer.add(pi); @@ -168,14 +148,10 @@ public class DefaultDocument extends AbstractDocument { } public ProcessingInstruction processingInstruction(String target) { - List source = contentList(); - int size = source.size(); - - for (int i = 0; i < size; i++) { - Object object = source.get(i); + for (Node node : contentList()) { - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; if (target.equals(pi.getName())) { return pi; @@ -187,13 +163,11 @@ public class DefaultDocument extends AbstractDocument { } public boolean removeProcessingInstruction(String target) { - List source = contentList(); + for (Iterator iter = contentList().iterator(); iter.hasNext();) { + Node node = iter.next(); - for (Iterator iter = source.iterator(); iter.hasNext();) { - Object object = iter.next(); - - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; if (target.equals(pi.getName())) { iter.remove(); @@ -206,25 +180,21 @@ public class DefaultDocument extends AbstractDocument { return false; } - public void setContent(List content) { + public void setContent(List content) { rootElement = null; contentRemoved(); if (content instanceof ContentListFacade) { - content = ((ContentListFacade) content).getBackingList(); + content = ((ContentListFacade) content).getBackingList(); } if (content == null) { this.content = null; } else { int size = content.size(); - List newContent = createContentList(size); - - for (int i = 0; i < size; i++) { - Object object = content.get(i); + List newContent = createContentList(size); - if (object instanceof Node) { - Node node = (Node) object; + for (Node node : content) { Document doc = node.getDocument(); if ((doc != null) && (doc != this)) { @@ -244,7 +214,6 @@ public class DefaultDocument extends AbstractDocument { newContent.add(node); childAdded(node); - } } this.content = newContent; @@ -263,7 +232,7 @@ public class DefaultDocument extends AbstractDocument { // Implementation methods // ------------------------------------------------------------------------- - protected List contentList() { + protected List contentList() { if (content == null) { content = createContentList(); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocumentType.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocumentType.java index c65fe7af7..4d27a2761 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocumentType.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultDocumentType.java @@ -7,6 +7,8 @@ package org.dom4j.tree; +import org.dom4j.dtd.Decl; + import java.util.List; /** @@ -16,7 +18,7 @@ import java.util.List; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ public class DefaultDocumentType extends AbstractDocumentType { /** The root element name of the document typ */ @@ -29,10 +31,10 @@ public class DefaultDocumentType extends AbstractDocumentType { private String systemID; /** The internal DTD declarations */ - private List internalDeclarations; + private List internalDeclarations; /** The external DTD declarations */ - private List externalDeclarations; + private List externalDeclarations; public DefaultDocumentType() { } @@ -119,19 +121,19 @@ public class DefaultDocumentType extends AbstractDocumentType { this.systemID = systemID; } - public List getInternalDeclarations() { + public List getInternalDeclarations() { return internalDeclarations; } - public void setInternalDeclarations(List internalDeclarations) { + public void setInternalDeclarations(List internalDeclarations) { this.internalDeclarations = internalDeclarations; } - public List getExternalDeclarations() { + public List getExternalDeclarations() { return externalDeclarations; } - public void setExternalDeclarations(List externalDeclarations) { + public void setExternalDeclarations(List externalDeclarations) { this.externalDeclarations = externalDeclarations; } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultElement.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultElement.java index a38d6b296..9787c71a1 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultElement.java @@ -7,21 +7,13 @@ package org.dom4j.tree; +import org.dom4j.*; + import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; -import org.dom4j.Attribute; -import org.dom4j.Branch; -import org.dom4j.Document; -import org.dom4j.DocumentFactory; -import org.dom4j.Element; -import org.dom4j.IllegalAddException; -import org.dom4j.Namespace; -import org.dom4j.Node; -import org.dom4j.ProcessingInstruction; -import org.dom4j.QName; - /** *

* DefaultElement is the default DOM4J default implementation of @@ -29,7 +21,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.59 $ */ public class DefaultElement extends AbstractElement { /** The DocumentFactory instance used by default */ @@ -141,7 +133,7 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; int size = list.size(); @@ -150,11 +142,9 @@ public class DefaultElement extends AbstractElement { // optimised to avoid StringBuffer creation return getContentAsStringValue(list.get(0)); } else { - StringBuffer buffer = new StringBuffer(); - - for (int i = 0; i < size; i++) { - Object node = list.get(i); + StringBuilder buffer = new StringBuilder(); + for (Node node : list) { String string = getContentAsStringValue(node); if (string.length() > 0) { @@ -209,15 +199,11 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; + for (Node node : list) { + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; if (prefix.equals(namespace.getPrefix())) { return namespace; @@ -243,7 +229,7 @@ public class DefaultElement extends AbstractElement { } } - if ((prefix == null) || (prefix.length() <= 0)) { + if ((prefix.length() <= 0)) { return Namespace.NO_NAMESPACE; } @@ -259,15 +245,11 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; - - int size = list.size(); + List list = (List) contentShadow; - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; + for (Node node : list) { + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; if (uri.equals(namespace.getURI())) { return namespace; @@ -292,8 +274,8 @@ public class DefaultElement extends AbstractElement { } } - public List declaredNamespaces() { - BackedList answer = createResultList(); + public List declaredNamespaces() { + BackedList answer = createResultList(); // if (getNamespaceURI().length() > 0) { // @@ -303,41 +285,33 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; - - int size = list.size(); + List list = (List) contentShadow; - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Namespace) { - answer.addLocal(object); + for (Node node : list) { + if (node instanceof Namespace) { + answer.addLocal((Namespace) node); } } } else { if (contentShadow instanceof Namespace) { - answer.addLocal(contentShadow); + answer.addLocal((Namespace) contentShadow); } } return answer; } - public List additionalNamespaces() { + public List additionalNamespaces() { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; - - int size = list.size(); - - BackedList answer = createResultList(); + List list = (List) contentShadow; - for (int i = 0; i < size; i++) { - Object object = list.get(i); + BackedList answer = createResultList(); - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; + for (Node node : list) { + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; if (!namespace.equals(getNamespace())) { answer.addLocal(namespace); @@ -361,21 +335,17 @@ public class DefaultElement extends AbstractElement { } } - public List additionalNamespaces(String defaultNamespaceURI) { + public List additionalNamespaces(String defaultNamespaceURI) { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; - - BackedList answer = createResultList(); + List list = (List) contentShadow; - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); + BackedList answer = createResultList(); - if (object instanceof Namespace) { - Namespace namespace = (Namespace) object; + for (Node node : list) { + if (node instanceof Namespace) { + Namespace namespace = (Namespace) node; if (!defaultNamespaceURI.equals(namespace.getURI())) { answer.addLocal(namespace); @@ -398,49 +368,41 @@ public class DefaultElement extends AbstractElement { } // Processing instruction API - public List processingInstructions() { + public List processingInstructions() { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; - BackedList answer = createResultList(); + BackedList answer = createResultList(); - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof ProcessingInstruction) { - answer.addLocal(object); + for (Node node : list) { + if (node instanceof ProcessingInstruction) { + answer.addLocal((ProcessingInstruction) node); } } return answer; } else { if (contentShadow instanceof ProcessingInstruction) { - return createSingleResultList(contentShadow); + return createSingleResultList((ProcessingInstruction) contentShadow); } return createEmptyList(); } } - public List processingInstructions(String target) { + public List processingInstructions(String target) { final Object shadow = content; if (shadow instanceof List) { - List list = (List) shadow; - - BackedList answer = createResultList(); - - int size = list.size(); + List list = (List) shadow; - for (int i = 0; i < size; i++) { - Object object = list.get(i); + BackedList answer = createResultList(); - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + for (Node node : list) { + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; if (target.equals(pi.getName())) { answer.addLocal(pi); @@ -466,15 +428,11 @@ public class DefaultElement extends AbstractElement { final Object shadow = content; if (shadow instanceof List) { - List list = (List) shadow; + List list = (List) shadow; - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + for (Node node : list) { + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; if (target.equals(pi.getName())) { return pi; @@ -498,13 +456,13 @@ public class DefaultElement extends AbstractElement { final Object shadow = content; if (shadow instanceof List) { - List list = (List) shadow; + List list = (List) shadow; - for (Iterator iter = list.iterator(); iter.hasNext();) { - Object object = iter.next(); + for (Iterator iter = list.iterator(); iter.hasNext();) { + Node node = iter.next(); - if (object instanceof ProcessingInstruction) { - ProcessingInstruction pi = (ProcessingInstruction) object; + if (node instanceof ProcessingInstruction) { + ProcessingInstruction pi = (ProcessingInstruction) node; if (target.equals(pi.getName())) { iter.remove(); @@ -532,15 +490,11 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; - - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); + List list = (List) contentShadow; - if (object instanceof Element) { - Element element = (Element) object; + for (Node node : list) { + if (node instanceof Element) { + Element element = (Element) node; if (name.equals(element.getName())) { return element; @@ -564,15 +518,11 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; - int size = list.size(); - - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Element) { - Element element = (Element) object; + for (Node node : list) { + if (node instanceof Element) { + Element element = (Element) node; if (qName.equals(element.getQName())) { return element; @@ -596,11 +546,11 @@ public class DefaultElement extends AbstractElement { return element(getDocumentFactory().createQName(name, namespace)); } - public void setContent(List content) { + public void setContent(List content) { contentRemoved(); if (content instanceof ContentListFacade) { - content = ((ContentListFacade) content).getBackingList(); + content = ((ContentListFacade) content).getBackingList(); } if (content == null) { @@ -608,27 +558,17 @@ public class DefaultElement extends AbstractElement { } else { int size = content.size(); - List newContent = createContentList(size); - - for (int i = 0; i < size; i++) { - Object object = content.get(i); - - if (object instanceof Node) { - Node node = (Node) object; - Element parent = node.getParent(); + List newContent = createContentList(size); - if ((parent != null) && (parent != this)) { - node = (Node) node.clone(); - } + for (Node node : content) { + Element parent = node.getParent(); - newContent.add(node); - childAdded(node); - } else if (object != null) { - String text = object.toString(); - Node node = getDocumentFactory().createText(text); - newContent.add(node); - childAdded(node); + if ((parent != null) && (parent != this)) { + node = (Node) node.clone(); } + + newContent.add(node); + childAdded(node); } this.content = newContent; @@ -646,10 +586,10 @@ public class DefaultElement extends AbstractElement { public Node node(int index) { if (index >= 0) { final Object contentShadow = content; - Object node; + Node node; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; if (index >= list.size()) { return null; @@ -657,16 +597,10 @@ public class DefaultElement extends AbstractElement { node = list.get(index); } else { - node = (index == 0) ? contentShadow : null; + node = (index == 0) ? (Node) contentShadow : null; } - if (node != null) { - if (node instanceof Node) { - return (Node) node; - } else { - return new DefaultText(node.toString()); - } - } + return node; } return null; @@ -676,7 +610,7 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; return list.indexOf(node); } else { @@ -692,7 +626,7 @@ public class DefaultElement extends AbstractElement { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; return list.size(); } else { @@ -700,45 +634,45 @@ public class DefaultElement extends AbstractElement { } } - public Iterator nodeIterator() { + public Iterator nodeIterator() { final Object contentShadow = content; if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; return list.iterator(); } else { if (contentShadow != null) { - return createSingleIterator(contentShadow); + return createSingleIterator((Node) contentShadow); } else { - return EMPTY_ITERATOR; + return Collections.emptyList().iterator(); } } } - public List attributes() { - return new ContentListFacade(this, attributeList()); + public List attributes() { + return new ContentListFacade(this, attributeList()); } - public void setAttributes(List attributes) { + public void setAttributes(List attributes) { if (attributes instanceof ContentListFacade) { - attributes = ((ContentListFacade) attributes).getBackingList(); + attributes = ((ContentListFacade) attributes).getBackingList(); } this.attributes = attributes; } - public Iterator attributeIterator() { + public Iterator attributeIterator() { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - List list = (List) attributesShadow; + List list = (List) attributesShadow; return list.iterator(); } else if (attributesShadow != null) { - return createSingleIterator(attributesShadow); + return createSingleIterator((Attribute) attributesShadow); } else { - return EMPTY_ITERATOR; + return Collections.emptyList().iterator(); } } @@ -746,7 +680,7 @@ public class DefaultElement extends AbstractElement { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - List list = (List) attributesShadow; + List list = (List) attributesShadow; return (Attribute) list.get(index); } else if ((attributesShadow != null) && (index == 0)) { @@ -760,7 +694,7 @@ public class DefaultElement extends AbstractElement { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - List list = (List) attributesShadow; + List list = (List) attributesShadow; return list.size(); } else { @@ -772,13 +706,9 @@ public class DefaultElement extends AbstractElement { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - List list = (List) attributesShadow; - - int size = list.size(); - - for (int i = 0; i < size; i++) { - Attribute attribute = (Attribute) list.get(i); + List list = (List) attributesShadow; + for (Attribute attribute : list) { if (name.equals(attribute.getName())) { return attribute; } @@ -798,13 +728,9 @@ public class DefaultElement extends AbstractElement { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - List list = (List) attributesShadow; - - int size = list.size(); - - for (int i = 0; i < size; i++) { - Attribute attribute = (Attribute) list.get(i); + List list = (List) attributesShadow; + for (Attribute attribute : list) { if (qName.equals(attribute.getQName())) { return attribute; } @@ -857,7 +783,7 @@ public class DefaultElement extends AbstractElement { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - List list = (List) attributesShadow; + List list = (List) attributesShadow; answer = list.remove(attribute); @@ -904,13 +830,13 @@ public class DefaultElement extends AbstractElement { this.content = node; } else { if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; list.add(node); } else { - List list = createContentList(); + List list = createContentList(); - list.add(contentShadow); + list.add((Node) contentShadow); list.add(node); @@ -931,7 +857,7 @@ public class DefaultElement extends AbstractElement { answer = true; } else if (contentShadow instanceof List) { - List list = (List) contentShadow; + List list = (List) contentShadow; answer = list.remove(node); } @@ -944,16 +870,16 @@ public class DefaultElement extends AbstractElement { return answer; } - protected List contentList() { + protected List contentList() { final Object contentShadow = content; if (contentShadow instanceof List) { - return (List) contentShadow; + return (List) contentShadow; } else { - List list = createContentList(); + List list = createContentList(); if (contentShadow != null) { - list.add(contentShadow); + list.add((Node) contentShadow); } this.content = list; @@ -962,21 +888,21 @@ public class DefaultElement extends AbstractElement { } } - protected List attributeList() { + protected List attributeList() { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - return (List) attributesShadow; + return (List) attributesShadow; } else if (attributesShadow != null) { - List list = createAttributeList(); + List list = createAttributeList(); - list.add(attributesShadow); + list.add((Attribute) attributesShadow); this.attributes = list; return list; } else { - List list = createAttributeList(); + List list = createAttributeList(); this.attributes = list; @@ -984,21 +910,21 @@ public class DefaultElement extends AbstractElement { } } - protected List attributeList(int size) { + protected List attributeList(int size) { final Object attributesShadow = this.attributes; if (attributesShadow instanceof List) { - return (List) attributesShadow; + return (List) attributesShadow; } else if (attributesShadow != null) { - List list = createAttributeList(size); + List list = createAttributeList(size); - list.add(attributesShadow); + list.add((Attribute) attributesShadow); this.attributes = list; return list; } else { - List list = createAttributeList(size); + List list = createAttributeList(size); this.attributes = list; @@ -1006,7 +932,7 @@ public class DefaultElement extends AbstractElement { } } - protected void setAttributeList(List attributeList) { + protected void setAttributeList(List attributeList) { this.attributes = attributeList; } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultEntity.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultEntity.java index 2854fd899..580a8d626 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultEntity.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultEntity.java @@ -17,7 +17,7 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ */ public class DefaultEntity extends FlyweightEntity { /** The parent of this node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultNamespace.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultNamespace.java index 4cc72a6b4..635b436e3 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultNamespace.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultNamespace.java @@ -18,7 +18,7 @@ import org.dom4j.Namespace; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.16 $ */ public class DefaultNamespace extends Namespace { /** The parent of this node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultProcessingInstruction.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultProcessingInstruction.java index a9fa5144f..7b2cadfd8 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultProcessingInstruction.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultProcessingInstruction.java @@ -7,10 +7,10 @@ package org.dom4j.tree; -import java.util.Map; - import org.dom4j.Element; +import java.util.Map; + /** *

* DefaultProcessingInstruction is the default Processing @@ -19,7 +19,7 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.13 $ */ public class DefaultProcessingInstruction extends org.dom4j.tree.FlyweightProcessingInstruction { @@ -36,7 +36,7 @@ public class DefaultProcessingInstruction extends * @param values * is the Map values for the PI */ - public DefaultProcessingInstruction(String target, Map values) { + public DefaultProcessingInstruction(String target, Map values) { super(target, values); } @@ -81,7 +81,7 @@ public class DefaultProcessingInstruction extends this.values = parseValues(text); } - public void setValues(Map values) { + public void setValues(Map values) { this.values = values; this.text = toString(values); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultText.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultText.java index 71a4996d5..c4e766cbc 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultText.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/DefaultText.java @@ -17,7 +17,7 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ */ public class DefaultText extends FlyweightText { /** The parent of this node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementIterator.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementIterator.java index 449c844db..5681f76b0 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementIterator.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementIterator.java @@ -10,6 +10,7 @@ package org.dom4j.tree; import java.util.Iterator; import org.dom4j.Element; +import org.dom4j.Node; /** *

@@ -18,12 +19,12 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ * * @deprecated THIS CLASS WILL BE REMOVED IN dom4j-1.6 !! */ -public class ElementIterator extends FilterIterator { - public ElementIterator(Iterator proxy) { +public class ElementIterator extends FilterIterator { + public ElementIterator(Iterator proxy) { super(proxy); } @@ -36,7 +37,7 @@ public class ElementIterator extends FilterIterator { * @return true if the given element implements the {@link Element} * interface */ - protected boolean matches(Object element) { + protected boolean matches(Node element) { return element instanceof Element; } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementNameIterator.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementNameIterator.java index 0266b23f8..1652e6e49 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementNameIterator.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementNameIterator.java @@ -10,6 +10,7 @@ package org.dom4j.tree; import java.util.Iterator; import org.dom4j.Element; +import org.dom4j.Node; /** *

@@ -19,14 +20,14 @@ import org.dom4j.Element; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ * * @deprecated THIS CLASS WILL BE REMOVED IN dom4j-1.6 !! */ -public class ElementNameIterator extends FilterIterator { +public class ElementNameIterator extends FilterIterator { private String name; - public ElementNameIterator(Iterator proxy, String name) { + public ElementNameIterator(Iterator proxy, String name) { super(proxy); this.name = name; } @@ -40,7 +41,7 @@ public class ElementNameIterator extends FilterIterator { * @return true if the given element implements the {@link Element} * interface */ - protected boolean matches(Object object) { + protected boolean matches(Node object) { if (object instanceof Element) { Element element = (Element) object; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementQNameIterator.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementQNameIterator.java index 7cdb2ee70..8054c4dad 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementQNameIterator.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/ElementQNameIterator.java @@ -10,6 +10,7 @@ package org.dom4j.tree; import java.util.Iterator; import org.dom4j.Element; +import org.dom4j.Node; import org.dom4j.QName; /** @@ -20,14 +21,14 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ * * @deprecated THIS CLASS WILL BE REMOVED IN dom4j-1.6 !! */ -public class ElementQNameIterator extends FilterIterator { +public class ElementQNameIterator extends FilterIterator { private QName qName; - public ElementQNameIterator(Iterator proxy, QName qName) { + public ElementQNameIterator(Iterator proxy, QName qName) { super(proxy); this.qName = qName; } @@ -41,7 +42,7 @@ public class ElementQNameIterator extends FilterIterator { * @return true if the given element implements the {@link Element} * interface and matches the given {@link QName} */ - protected boolean matches(Object object) { + protected boolean matches(Node object) { if (object instanceof Element) { Element element = (Element) object; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/FilterIterator.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/FilterIterator.java index da6fd9ff3..b24eaa346 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/FilterIterator.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/FilterIterator.java @@ -17,18 +17,18 @@ import java.util.NoSuchElementException; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ * * @deprecated THIS CLASS WILL BE REMOVED IN dom4j-1.6 !! */ -public abstract class FilterIterator implements Iterator { - protected Iterator proxy; +public abstract class FilterIterator implements Iterator { + protected Iterator proxy; - private Object next; + private T next; private boolean first = true; - public FilterIterator(Iterator proxy) { + public FilterIterator(Iterator proxy) { this.proxy = proxy; } @@ -41,12 +41,12 @@ public abstract class FilterIterator implements Iterator { return next != null; } - public Object next() throws NoSuchElementException { + public T next() throws NoSuchElementException { if (!hasNext()) { throw new NoSuchElementException(); } - Object answer = this.next; + T answer = this.next; this.next = findNext(); return answer; @@ -72,12 +72,12 @@ public abstract class FilterIterator implements Iterator { * @return true if the given element matches the filter and should be appear * in the iteration */ - protected abstract boolean matches(Object element); + protected abstract boolean matches(T element); - protected Object findNext() { + protected T findNext() { if (proxy != null) { while (proxy.hasNext()) { - Object nextObject = proxy.next(); + T nextObject = proxy.next(); if ((nextObject != null) && matches(nextObject)) { return nextObject; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightAttribute.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightAttribute.java index 20c9a8cac..307e60788 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightAttribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightAttribute.java @@ -22,7 +22,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class FlyweightAttribute extends AbstractAttribute { /** The QName for this element */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightCDATA.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightCDATA.java index 24cfbdb65..649c8848b 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightCDATA.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightCDATA.java @@ -23,7 +23,7 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ public class FlyweightCDATA extends AbstractCDATA implements CDATA { /** Text of the CDATA node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightComment.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightComment.java index 2ef8d39e9..3b322d615 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightComment.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightComment.java @@ -23,7 +23,7 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class FlyweightComment extends AbstractComment implements Comment { /** Text of the Comment node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightEntity.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightEntity.java index 6a8c9cbb2..63601e67d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightEntity.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightEntity.java @@ -23,12 +23,12 @@ import org.dom4j.Node; * *

* Often this node needs to be created and then the text content added later - * (for example in SAX) so this implementation allows a call to {@link#setText} + * (for example in SAX) so this implementation allows a call to {@link #setText} * providing the entity has no text already. *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.6 $ */ public class FlyweightEntity extends AbstractEntity { /** The name of the Entity */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightProcessingInstruction.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightProcessingInstruction.java index 997c3614b..cbde0dfba 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightProcessingInstruction.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightProcessingInstruction.java @@ -7,12 +7,12 @@ package org.dom4j.tree; -import java.util.Collections; -import java.util.Map; - import org.dom4j.Element; import org.dom4j.Node; +import java.util.Collections; +import java.util.Map; + /** *

* FlyweightProcessingInstruction is a Flyweight pattern @@ -25,7 +25,7 @@ import org.dom4j.Node; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class FlyweightProcessingInstruction extends AbstractProcessingInstruction { @@ -36,7 +36,7 @@ public class FlyweightProcessingInstruction extends protected String text; /** The values for the PI in name/value pairs */ - protected Map values; + protected Map values; /** * A default constructor for implementors to use. @@ -54,7 +54,7 @@ public class FlyweightProcessingInstruction extends * @param values * is the Map of the values for the PI */ - public FlyweightProcessingInstruction(String target, Map values) { + public FlyweightProcessingInstruction(String target, Map values) { this.target = target; this.values = values; this.text = toString(values); @@ -99,7 +99,7 @@ public class FlyweightProcessingInstruction extends return answer; } - public Map getValues() { + public Map getValues() { return Collections.unmodifiableMap(values); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightText.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightText.java index a42eef174..9ba321f5e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightText.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/FlyweightText.java @@ -23,7 +23,7 @@ import org.dom4j.Text; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class FlyweightText extends AbstractText implements Text { /** Text of the Text node */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceCache.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceCache.java index 70d879eb0..f5b3c5d19 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceCache.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceCache.java @@ -7,11 +7,11 @@ package org.dom4j.tree; +import org.dom4j.Namespace; + import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; import java.util.Map; - -import org.dom4j.Namespace; +import java.util.concurrent.ConcurrentHashMap; /** *

@@ -23,47 +23,25 @@ import org.dom4j.Namespace; * @author James Strachan * @author Maarten Coene * @author Brett Finnell - * @version $Revision$ + * @version $Revision: 1.15 $ */ public class NamespaceCache { - private static final String CONCURRENTREADERHASHMAP_CLASS - = "EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap"; /** * Cache of {@link Map}instances indexed by URI which contain caches of * {@link Namespace}for each prefix */ - protected static Map cache; + protected static Map>> cache; /** * Cache of {@link Namespace}instances indexed by URI for default * namespaces with no prefixes */ - protected static Map noPrefixCache; + protected static Map> noPrefixCache; static { - /* Try the java.util.concurrent.ConcurrentHashMap first. */ - try { - Class clazz = Class - .forName("java.util.concurrent.ConcurrentHashMap"); - Constructor construct = clazz.getConstructor(new Class[] { - Integer.TYPE, Float.TYPE, Integer.TYPE }); - cache = (Map) construct.newInstance(new Object[] {new Integer(11), - new Float(0.75f), new Integer(1) }); - noPrefixCache = (Map) construct.newInstance(new Object[] { - new Integer(11), new Float(0.75f), new Integer(1) }); - } catch (Throwable t1) { - /* Try to use the util.concurrent library (if in classpath) */ - try { - Class clazz = Class.forName(CONCURRENTREADERHASHMAP_CLASS); - cache = (Map) clazz.newInstance(); - noPrefixCache = (Map) clazz.newInstance(); - } catch (Throwable t2) { - /* If previous implementations fail, use internal one */ - cache = new ConcurrentReaderHashMap(); - noPrefixCache = new ConcurrentReaderHashMap(); - } - } + cache = new ConcurrentHashMap>>(); + noPrefixCache = new ConcurrentHashMap>(); } /** @@ -77,25 +55,25 @@ public class NamespaceCache { * @return the namespace for the given prefix and uri */ public Namespace get(String prefix, String uri) { - Map uriCache = getURICache(uri); - WeakReference ref = (WeakReference) uriCache.get(prefix); + Map> uriCache = getURICache(uri); + WeakReference ref = uriCache.get(prefix); Namespace answer = null; if (ref != null) { - answer = (Namespace) ref.get(); + answer = ref.get(); } if (answer == null) { synchronized (uriCache) { - ref = (WeakReference) uriCache.get(prefix); + ref = uriCache.get(prefix); if (ref != null) { - answer = (Namespace) ref.get(); + answer = ref.get(); } if (answer == null) { answer = createNamespace(prefix, uri); - uriCache.put(prefix, new WeakReference(answer)); + uriCache.put(prefix, new WeakReference(answer)); } } } @@ -112,24 +90,24 @@ public class NamespaceCache { * @return the name model for the given name and namepsace */ public Namespace get(String uri) { - WeakReference ref = (WeakReference) noPrefixCache.get(uri); + WeakReference ref = noPrefixCache.get(uri); Namespace answer = null; if (ref != null) { - answer = (Namespace) ref.get(); + answer = ref.get(); } if (answer == null) { synchronized (noPrefixCache) { - ref = (WeakReference) noPrefixCache.get(uri); + ref = noPrefixCache.get(uri); if (ref != null) { - answer = (Namespace) ref.get(); + answer = ref.get(); } if (answer == null) { answer = createNamespace("", uri); - noPrefixCache.put(uri, new WeakReference(answer)); + noPrefixCache.put(uri, new WeakReference(answer)); } } } @@ -146,15 +124,15 @@ public class NamespaceCache { * @return the cache for the given namespace URI. If one does not currently * exist it is created. */ - protected Map getURICache(String uri) { - Map answer = (Map) cache.get(uri); + protected Map> getURICache(String uri) { + Map> answer = cache.get(uri); if (answer == null) { synchronized (cache) { - answer = (Map) cache.get(uri); + answer = cache.get(uri); if (answer == null) { - answer = new ConcurrentReaderHashMap(); + answer = new ConcurrentHashMap>(); cache.put(uri, answer); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceStack.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceStack.java index ec1780840..5eac67024 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceStack.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/NamespaceStack.java @@ -7,43 +7,43 @@ package org.dom4j.tree; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - import org.dom4j.DocumentFactory; import org.dom4j.Namespace; import org.dom4j.QName; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + /** * NamespaceStack implements a stack of namespaces and optionally maintains a * cache of all the fully qualified names (QName) which are in * scope. This is useful when building or navigating a dom4j document. * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.13 $ */ public class NamespaceStack { /** The factory used to create new Namespace instances */ private DocumentFactory documentFactory; /** The Stack of namespaces */ - private ArrayList namespaceStack = new ArrayList(); + private ArrayList namespaceStack = new ArrayList(); /** The cache of qualifiedNames to QNames per namespace context */ - private ArrayList namespaceCacheList = new ArrayList(); + private ArrayList> namespaceCacheList = new ArrayList>(); /** * A cache of current namespace context cache of mapping from qualifiedName * to QName */ - private Map currentNamespaceCache; + private Map currentNamespaceCache; /** * A cache of mapping from qualifiedName to QName before any namespaces are * declared */ - private Map rootNamespaceCache = new HashMap(); + private Map rootNamespaceCache = new HashMap(); /** Caches the default namespace defined via xmlns="" */ private Namespace defaultNamespace; @@ -112,7 +112,7 @@ public class NamespaceStack { * @return the namespace at the specified index on the stack */ public Namespace getNamespace(int index) { - return (Namespace) namespaceStack.get(index); + return namespaceStack.get(index); } /** @@ -130,7 +130,7 @@ public class NamespaceStack { } for (int i = namespaceStack.size() - 1; i >= 0; i--) { - Namespace namespace = (Namespace) namespaceStack.get(i); + Namespace namespace = namespaceStack.get(i); if (prefix.equals(namespace.getPrefix())) { return namespace; @@ -164,7 +164,7 @@ public class NamespaceStack { */ public boolean contains(Namespace namespace) { String prefix = namespace.getPrefix(); - Namespace current = null; + Namespace current; if ((prefix == null) || (prefix.length() == 0)) { current = getDefaultNamespace(); @@ -219,8 +219,8 @@ public class NamespaceStack { qualifiedName = localName; } - Map map = getNamespaceCache(); - QName answer = (QName) map.get(qualifiedName); + Map map = getNamespaceCache(); + QName answer = map.get(qualifiedName); if (answer != null) { return answer; @@ -234,7 +234,7 @@ public class NamespaceStack { namespaceURI = ""; } - Namespace namespace = null; + Namespace namespace; String prefix = ""; int index = qualifiedName.indexOf(":"); @@ -310,7 +310,7 @@ public class NamespaceStack { Namespace namespace = null; for (int i = namespaceStack.size() - 1; i >= 0; i--) { - Namespace ns = (Namespace) namespaceStack.get(i); + Namespace ns = namespaceStack.get(i); if (prefix.equals(ns.getPrefix())) { remove(i); @@ -415,7 +415,7 @@ public class NamespaceStack { */ protected Namespace findDefaultNamespace() { for (int i = namespaceStack.size() - 1; i >= 0; i--) { - Namespace namespace = (Namespace) namespaceStack.get(i); + Namespace namespace = namespaceStack.get(i); if (namespace != null) { String prefix = namespace.getPrefix(); @@ -438,7 +438,7 @@ public class NamespaceStack { * @return DOCUMENT ME! */ protected Namespace remove(int index) { - Namespace namespace = (Namespace) namespaceStack.remove(index); + Namespace namespace = namespaceStack.remove(index); namespaceCacheList.remove(index); defaultNamespace = null; currentNamespaceCache = null; @@ -446,17 +446,17 @@ public class NamespaceStack { return namespace; } - protected Map getNamespaceCache() { + protected Map getNamespaceCache() { if (currentNamespaceCache == null) { int index = namespaceStack.size() - 1; if (index < 0) { currentNamespaceCache = rootNamespaceCache; } else { - currentNamespaceCache = (Map) namespaceCacheList.get(index); + currentNamespaceCache = namespaceCacheList.get(index); if (currentNamespaceCache == null) { - currentNamespaceCache = new HashMap(); + currentNamespaceCache = new HashMap(); namespaceCacheList.set(index, currentNamespaceCache); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/QNameCache.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/QNameCache.java index 345a09345..ee856c3a3 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/QNameCache.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/QNameCache.java @@ -7,41 +7,30 @@ package org.dom4j.tree; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - import org.dom4j.DocumentFactory; import org.dom4j.Namespace; import org.dom4j.QName; +import java.util.*; + /** *

* QNameCache caches instances of QName for reuse * both across documents and within documents. - *

< < < < < < < QNameCache.java - * + * * @author James Strachan - * @version $Revision$ ======= + * @version $Revision: 1.16 $ * - * @author James Strachan - * @version $Revision$ >>>>>>> 1.15 */ public class QNameCache { /** Cache of {@link QName}instances with no namespace */ - protected Map noNamespaceCache = Collections - .synchronizedMap(new WeakHashMap()); + protected Map noNamespaceCache = Collections.synchronizedMap(new WeakHashMap()); /** * Cache of {@link Map}instances indexed by namespace which contain caches * of {@link QName}for each name */ - protected Map namespaceCache = Collections - .synchronizedMap(new WeakHashMap()); + protected Map> namespaceCache = Collections.synchronizedMap(new WeakHashMap>()); /** * The document factory associated with new QNames instances in this cache @@ -61,14 +50,17 @@ public class QNameCache { * * @return DOCUMENT ME! */ - public List getQNames() { - List answer = new ArrayList(); - answer.addAll(noNamespaceCache.values()); - - for (Iterator it = namespaceCache.values().iterator(); it.hasNext();) { - Map map = (Map) it.next(); - answer.addAll(map.values()); - } + public List getQNames() { + List answer = new ArrayList(); + synchronized(noNamespaceCache) { + answer.addAll(noNamespaceCache.values()); + } + + synchronized(namespaceCache) { + for (Map map : namespaceCache.values()) { + answer.addAll(map.values()); + } + } return answer; } @@ -85,7 +77,7 @@ public class QNameCache { QName answer = null; if (name != null) { - answer = (QName) noNamespaceCache.get(name); + answer = noNamespaceCache.get(name); } else { name = ""; } @@ -110,11 +102,11 @@ public class QNameCache { * @return the QName for the given local name and namepsace */ public QName get(String name, Namespace namespace) { - Map cache = getNamespaceCache(namespace); + Map cache = getNamespaceCache(namespace); QName answer = null; if (name != null) { - answer = (QName) cache.get(name); + answer = cache.get(name); } else { name = ""; } @@ -141,11 +133,11 @@ public class QNameCache { * @return the QName for the given local name, qualified name and namepsace */ public QName get(String localName, Namespace namespace, String qName) { - Map cache = getNamespaceCache(namespace); + Map cache = getNamespaceCache(namespace); QName answer = null; if (localName != null) { - answer = (QName) cache.get(localName); + answer = cache.get(localName); } else { localName = ""; } @@ -164,6 +156,8 @@ public class QNameCache { if (index < 0) { return get(qualifiedName, Namespace.get(uri)); + } else if (index == 0){ + throw new IllegalArgumentException("Qualified name cannot start with ':'."); } else { String name = qualifiedName.substring(index + 1); String prefix = qualifiedName.substring(0, index); @@ -195,15 +189,15 @@ public class QNameCache { * @return the cache for the given namespace. If one does not currently * exist it is created. */ - protected Map getNamespaceCache(Namespace namespace) { + protected Map getNamespaceCache(Namespace namespace) { if (namespace == Namespace.NO_NAMESPACE) { return noNamespaceCache; } - Map answer = null; + Map answer = null; if (namespace != null) { - answer = (Map) namespaceCache.get(namespace); + answer = namespaceCache.get(namespace); } if (answer == null) { @@ -219,8 +213,8 @@ public class QNameCache { * * @return a newly created {@link Map}instance. */ - protected Map createMap() { - return Collections.synchronizedMap(new HashMap()); + protected Map createMap() { + return Collections.synchronizedMap(new HashMap()); } /** @@ -307,4 +301,4 @@ public class QNameCache { * POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file + */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/SingleIterator.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/SingleIterator.java index 9c76cef87..6a53c421c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/SingleIterator.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/SingleIterator.java @@ -16,14 +16,14 @@ import java.util.Iterator; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ -public class SingleIterator implements Iterator { +public class SingleIterator implements Iterator { private boolean first = true; - private Object object; + private T object; - public SingleIterator(Object object) { + public SingleIterator(T object) { this.object = object; } @@ -31,8 +31,8 @@ public class SingleIterator implements Iterator { return first; } - public Object next() { - Object answer = object; + public T next() { + T answer = object; object = null; first = false; diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/tree/package-info.java new file mode 100644 index 000000000..c3f763ebe --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/tree/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the default implementations of the dom4j Document Object Model together with some helpful base classes for those wishing to implement their own document object model. + */ +package org.dom4j.tree; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/tree/package.html b/fine-org-dom4j/src/main/java/org/dom4j/tree/package.html deleted file mode 100644 index 221bc7972..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/tree/package.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - -

Contains the default implementations of the dom4j Document Object Model - together with some helpful base classes for those wishing to - implement their own document object model. -

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/AttributeHelper.java b/fine-org-dom4j/src/main/java/org/dom4j/util/AttributeHelper.java index 83ed54cb9..ee85331b6 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/AttributeHelper.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/AttributeHelper.java @@ -18,7 +18,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class AttributeHelper { protected AttributeHelper() { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedDocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedDocumentFactory.java index ec7cd388c..579c9627d 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedDocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedDocumentFactory.java @@ -20,7 +20,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class IndexedDocumentFactory extends DocumentFactory { /** The Singleton instance */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedElement.java b/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedElement.java index e7550ce75..467835f06 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/IndexedElement.java @@ -18,24 +18,37 @@ import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.QName; import org.dom4j.tree.BackedList; +import org.dom4j.tree.DefaultAttribute; import org.dom4j.tree.DefaultElement; /** - *

* IndexedElement is an implementation of {@link Element}which * maintains an index of the attributes and elements it contains to optimise * lookups via name. - *

- * + * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ +@SuppressWarnings("unused") public class IndexedElement extends DefaultElement { - /** Lazily constructed index for elements */ - private Map elementIndex; + /** + * Lazily constructed index for elements + * + * Keys are of type QName and String + * + * Values are of type Element and List<Element> + */ + + private Map elementIndex; - /** Lazily constructed index for attributes */ - private Map attributeIndex; + /** + * Lazily constructed index for attributes + + * Keys are of type QName and String + * + * Values are of type <A> + */ + private Map attributeIndex; public IndexedElement(String name) { super(name); @@ -50,11 +63,11 @@ public class IndexedElement extends DefaultElement { } public Attribute attribute(String name) { - return (Attribute) attributeIndex().get(name); + return attributeIndex().get(name); } public Attribute attribute(QName qName) { - return (Attribute) attributeIndex().get(qName); + return attributeIndex().get(qName); } public Element element(String name) { @@ -65,11 +78,11 @@ public class IndexedElement extends DefaultElement { return asElement(elementIndex().get(qName)); } - public List elements(String name) { + public List elements(String name) { return asElementList(elementIndex().get(name)); } - public List elements(QName qName) { + public List elements(QName qName) { return asElementList(elementIndex().get(qName)); } @@ -79,25 +92,25 @@ public class IndexedElement extends DefaultElement { if (object instanceof Element) { return (Element) object; } else if (object != null) { - List list = (List) object; + List list = (List) object; if (list.size() >= 1) { - return (Element) list.get(0); + return list.get(0); } } return null; } - protected List asElementList(Object object) { + protected List asElementList(Object object) { if (object instanceof Element) { - return createSingleResultList(object); + return createSingleResultList((Element) object); } else if (object != null) { - List list = (List) object; - BackedList answer = createResultList(); + List list = (List) object; + BackedList answer = createResultList(); - for (int i = 0, size = list.size(); i < size; i++) { - answer.addLocal(list.get(i)); + for (Element aList : list) { + answer.addLocal(aList); } return answer; @@ -116,7 +129,7 @@ public class IndexedElement extends DefaultElement { * * @deprecated WILL BE REMOVED IN dom4j-1.6 !! */ - protected Iterator asElementIterator(Object object) { + protected Iterator asElementIterator(Object object) { return asElementList(object).iterator(); } @@ -145,24 +158,24 @@ public class IndexedElement extends DefaultElement { return false; } - protected Map attributeIndex() { + protected Map attributeIndex() { if (attributeIndex == null) { attributeIndex = createAttributeIndex(); - for (Iterator iter = attributeIterator(); iter.hasNext();) { - addToAttributeIndex((Attribute) iter.next()); + for (Iterator iter = attributeIterator(); iter.hasNext();) { + addToAttributeIndex(iter.next()); } } return attributeIndex; } - protected Map elementIndex() { + protected Map elementIndex() { if (elementIndex == null) { elementIndex = createElementIndex(); - for (Iterator iter = elementIterator(); iter.hasNext();) { - addToElementIndex((Element) iter.next()); + for (Iterator iter = elementIterator(); iter.hasNext();) { + addToElementIndex(iter.next()); } } @@ -174,10 +187,9 @@ public class IndexedElement extends DefaultElement { * * @return DOCUMENT ME! */ - protected Map createAttributeIndex() { - Map answer = createIndex(); + protected Map createAttributeIndex() { - return answer; + return createIndex(); } /** @@ -185,10 +197,9 @@ public class IndexedElement extends DefaultElement { * * @return DOCUMENT ME! */ - protected Map createElementIndex() { - Map answer = createIndex(); + protected Map createElementIndex() { - return answer; + return createIndex(); } protected void addToElementIndex(Element element) { @@ -205,11 +216,11 @@ public class IndexedElement extends DefaultElement { elementIndex.put(key, value); } else { if (oldValue instanceof List) { - List list = (List) oldValue; + List list = (List) oldValue; list.add(value); } else { - List list = createList(); - list.add(oldValue); + List list = createList(); + list.add((Element) oldValue); list.add(value); elementIndex.put(key, list); } @@ -227,7 +238,7 @@ public class IndexedElement extends DefaultElement { Object oldValue = elementIndex.get(key); if (oldValue instanceof List) { - List list = (List) oldValue; + List list = (List) oldValue; list.remove(value); } else { elementIndex.remove(key); @@ -266,20 +277,22 @@ public class IndexedElement extends DefaultElement { /** * Factory method to return a new map implementation for indices - * + * + * @param DOCUMENT ME! * @return DOCUMENT ME! */ - protected Map createIndex() { - return new HashMap(); + protected Map createIndex() { + return new HashMap(); } /** * Factory method to return a list implementation for indices - * + * + * @param DOCUMENT ME! * @return DOCUMENT ME! */ - protected List createList() { - return new ArrayList(); + protected List createList() { + return new ArrayList(); } } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/NodeComparator.java b/fine-org-dom4j/src/main/java/org/dom4j/util/NodeComparator.java index fb81f372d..2c1b4c6a7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/NodeComparator.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/NodeComparator.java @@ -31,86 +31,9 @@ import org.dom4j.Text; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.10 $ */ -public class NodeComparator implements Comparator { - /** - * Compares its two arguments for order. Returns a negative integer, zero, - * or a positive integer as the first argument is less than, equal to, or - * greater than the second. - * - *

- * The implementor must ensure that sgn(compare(x, y)) == - * -sgn(compare(y, x)) - * for all x and y. (This implies that - * compare(x, y) must throw an exception if and only if - * compare(y, x) throws an exception.) - *

- * - *

- * The implementor must also ensure that the relation is transitive: - * ((compare(x, y)>0) && (compare(y, z)>0)) implies - * compare(x, z)>0. - *

- * - *

- * Finally, the implementer must ensure that compare(x, y)==0 - * implies that sgn(compare(x, z))==sgn(compare(y, z)) for all - * z. - *

- * - *

- * It is generally the case, but not strictly required that - * (compare(x, y)==0) == (x.equals(y)). Generally speaking, any - * comparator that violates this condition should clearly indicate this - * fact. The recommended language is "Note: this comparator imposes - * orderings that are inconsistent with equals." - *

- * - * @param o1 - * the first object to be compared. - * @param o2 - * the second object to be compared. - * - * @return a negative integer, zero, or a positive integer as the first - * argument is less than, equal to, or greater than the second. - */ - public int compare(Object o1, Object o2) { - if (o1 == o2) { - return 0; - } else if (o1 == null) { - // null is less - return -1; - } else if (o2 == null) { - return 1; - } - - if (o1 instanceof Node) { - if (o2 instanceof Node) { - return compare((Node) o1, (Node) o2); - } else { - // Node implementations are greater - return 1; - } - } else { - if (o2 instanceof Node) { - // Node implementations are greater - return -1; - } else { - if (o1 instanceof Comparable) { - Comparable c1 = (Comparable) o1; - - return c1.compareTo(o2); - } else { - String name1 = o1.getClass().getName(); - String name2 = o2.getClass().getName(); - - return name1.compareTo(name2); - } - } - } - } - +public class NodeComparator implements Comparator { public int compare(Node n1, Node n2) { int nodeType1 = n1.getNodeType(); int nodeType2 = n2.getNodeType(); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyDocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyDocumentFactory.java index 9dfab380f..afd769cb6 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyDocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyDocumentFactory.java @@ -20,7 +20,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.9 $ */ public class NonLazyDocumentFactory extends DocumentFactory { /** The Singleton instance */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyElement.java b/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyElement.java index ce993765e..20033b902 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/NonLazyElement.java @@ -18,7 +18,7 @@ import org.dom4j.tree.BaseElement; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ public class NonLazyElement extends BaseElement { public NonLazyElement(String name) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/PerThreadSingleton.java b/fine-org-dom4j/src/main/java/org/dom4j/util/PerThreadSingleton.java index 1095f353b..ac8bbec1c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/PerThreadSingleton.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/PerThreadSingleton.java @@ -18,41 +18,41 @@ import java.lang.ref.WeakReference; *

* * @author David Lucas - * @version $Revision$ + * @version $Revision: 1.3 $ */ -public class PerThreadSingleton implements SingletonStrategy { +public class PerThreadSingleton implements SingletonStrategy { private String singletonClassName = null; - private ThreadLocal perThreadCache = new ThreadLocal(); + private ThreadLocal> perThreadCache = new ThreadLocal>(); public PerThreadSingleton() { } public void reset() { - perThreadCache = new ThreadLocal(); + perThreadCache = new ThreadLocal>(); } - public Object instance() { - Object singletonInstancePerThread = null; + public T instance() { + T singletonInstancePerThread = null; // use weak reference to prevent cyclic reference during GC - WeakReference ref = (WeakReference) perThreadCache.get(); + WeakReference ref = (WeakReference) perThreadCache.get(); // singletonInstancePerThread=perThreadCache.get(); // if (singletonInstancePerThread==null) { if (ref == null || ref.get() == null) { - Class clazz = null; + Class clazz = null; try { - clazz = Thread.currentThread().getContextClassLoader().loadClass( + clazz = (Class) Thread.currentThread().getContextClassLoader().loadClass( singletonClassName); singletonInstancePerThread = clazz.newInstance(); } catch (Exception ignore) { try { - clazz = Class.forName(singletonClassName); + clazz = (Class) Class.forName(singletonClassName); singletonInstancePerThread = clazz.newInstance(); } catch (Exception ignore2) { } } - perThreadCache.set(new WeakReference(singletonInstancePerThread)); + perThreadCache.set(new WeakReference(singletonInstancePerThread)); } else { singletonInstancePerThread = ref.get(); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/ProxyDocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/util/ProxyDocumentFactory.java index 61a120b0b..65624be29 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/ProxyDocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/ProxyDocumentFactory.java @@ -37,7 +37,7 @@ import org.jaxen.VariableContext; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.13 $ */ public abstract class ProxyDocumentFactory { private DocumentFactory proxy; @@ -108,7 +108,7 @@ public abstract class ProxyDocumentFactory { } public ProcessingInstruction createProcessingInstruction(String target, - Map data) { + Map data) { return proxy.createProcessingInstruction(target, data); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/SimpleSingleton.java b/fine-org-dom4j/src/main/java/org/dom4j/util/SimpleSingleton.java index 49757ef1f..747f5c48e 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/SimpleSingleton.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/SimpleSingleton.java @@ -16,31 +16,31 @@ package org.dom4j.util; *

* * @author David Lucas - * @version $Revision$ + * @version $Revision: 1.3 $ */ -public class SimpleSingleton implements SingletonStrategy { +public class SimpleSingleton implements SingletonStrategy { private String singletonClassName = null; - private Object singletonInstance = null; + private T singletonInstance = null; public SimpleSingleton() { } - public Object instance() { + public T instance() { return singletonInstance; } public void reset() { if (singletonClassName != null) { - Class clazz = null; + Class clazz; try { - clazz = Thread.currentThread().getContextClassLoader().loadClass( + clazz = (Class) Thread.currentThread().getContextClassLoader().loadClass( singletonClassName); singletonInstance = clazz.newInstance(); } catch (Exception ignore) { try { - clazz = Class.forName(singletonClassName); + clazz = (Class) Class.forName(singletonClassName); singletonInstance = clazz.newInstance(); } catch (Exception ignore2) { } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/SingletonStrategy.java b/fine-org-dom4j/src/main/java/org/dom4j/util/SingletonStrategy.java index 77c4d37cf..42db649a6 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/SingletonStrategy.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/SingletonStrategy.java @@ -8,22 +8,20 @@ package org.dom4j.util; /** - *

* SingletonStrategy is an interface used to provide common * factory access for the same object based on an implementation strategy for * singleton. Right now there are two that accompany this interface: * SimpleSingleton and PerThreadSingleton. This will replace previous usage of * ThreadLocal to allow for alternate strategies. - *

- * + * * @author David Lucas - * @version $Revision$ + * @version $Revision: 1.2 $ */ -public interface SingletonStrategy { +public interface SingletonStrategy { /** - * return a singleton instance of the class specified in setSingletonClass + * @return a singleton instance of the class specified in setSingletonClass */ - Object instance(); + T instance(); /** * reset the instance to a new instance for the implemented strategy @@ -34,6 +32,8 @@ public interface SingletonStrategy { * set a singleton class name that will be used to create the singleton * based on the strategy implementation of this interface. The default * constructor of the class will be used and must be public. + * + * @param singletonClassName DOCUMENT ME! */ void setSingletonClassName(String singletonClassName); } diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/StringUtils.java b/fine-org-dom4j/src/main/java/org/dom4j/util/StringUtils.java new file mode 100644 index 000000000..694e3b99e --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/StringUtils.java @@ -0,0 +1,44 @@ +package org.dom4j.util; + +/** + * Contains utilities related to strings. + * + * @author Marián Petráš + */ +public final class StringUtils { + + private StringUtils() {} + + /** + * Finds out if the given character sequence starts with a whitespace + * character. + * + * @return {@code true} if the given character sequence is not empty + * and starts with a whitespace character; {@code false} otherwise + * @exception NullPointerException if the given character sequence is + * {@code null} + */ + public static boolean startsWithWhitespace(final CharSequence charSeq) { + if (charSeq.length() == 0) { + return false; + } + return Character.isWhitespace(charSeq.charAt(0)); + } + + /** + * Finds out if the given character sequence ends with a whitespace + * character. + * + * @return {@code true} if the given character sequence is not empty + * and ends with a whitespace character; {@code false} otherwise + * @exception NullPointerException if the given character sequence is + * {@code null} + */ + public static boolean endsWithWhitespace(final CharSequence charSeq) { + if (charSeq.length() == 0) { + return false; + } + return Character.isWhitespace(charSeq.charAt(charSeq.length() - 1)); + } + +} diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataAttribute.java b/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataAttribute.java index 2c77f7c1e..2ede78d71 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataAttribute.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataAttribute.java @@ -20,7 +20,7 @@ import org.dom4j.tree.DefaultAttribute; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.8 $ */ public class UserDataAttribute extends DefaultAttribute { /** The user data object */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataDocumentFactory.java b/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataDocumentFactory.java index 1bae185a9..17c5154ef 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataDocumentFactory.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataDocumentFactory.java @@ -23,7 +23,7 @@ import org.dom4j.QName; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.11 $ */ public class UserDataDocumentFactory extends DocumentFactory { /** The Singleton instance */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataElement.java b/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataElement.java index d4cd400fe..24fe685cb 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataElement.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/UserDataElement.java @@ -21,7 +21,7 @@ import org.dom4j.tree.DefaultElement; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.12 $ */ public class UserDataElement extends DefaultElement { /** The user data object */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/XMLErrorHandler.java b/fine-org-dom4j/src/main/java/org/dom4j/util/XMLErrorHandler.java index fd8dbed53..f1c9ebc34 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/XMLErrorHandler.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/XMLErrorHandler.java @@ -20,7 +20,7 @@ import org.xml.sax.SAXParseException; * the errors can be included in a SOAP message. * * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.7 $ */ public class XMLErrorHandler implements ErrorHandler { protected static final QName ERROR_QNAME = QName.get("error"); diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/util/package-info.java new file mode 100644 index 000000000..d458bca15 --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/util/package-info.java @@ -0,0 +1,4 @@ +/** + * A collection of utility classes for the dom4j API. + */ +package org.dom4j.util; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/util/package.html b/fine-org-dom4j/src/main/java/org/dom4j/util/package.html deleted file mode 100644 index 9a8aac3dd..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/util/package.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - -

A collection of utility classes for the dom4j API.

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpath/DefaultXPath.java b/fine-org-dom4j/src/main/java/org/dom4j/xpath/DefaultXPath.java index b94f434dc..f81eec5e7 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/xpath/DefaultXPath.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/xpath/DefaultXPath.java @@ -86,7 +86,7 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { return namespaceContext; } - public void setNamespaceURIs(Map map) { + public void setNamespaceURIs(Map map) { setNamespaceContext(new SimpleNamespaceContext(map)); } @@ -107,7 +107,7 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { try { setNSContext(context); - List answer = xpath.selectNodes(context); + List answer = xpath.selectNodes(context); if ((answer != null) && (answer.size() == 1)) { return answer.get(0); @@ -125,28 +125,28 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { return evaluate(context); } - public List selectNodes(Object context) { + public List selectNodes(Object context) { try { setNSContext(context); - return xpath.selectNodes(context); + return (List) xpath.selectNodes(context); } catch (JaxenException e) { handleJaxenException(e); - return Collections.EMPTY_LIST; + return Collections.emptyList(); } } - public List selectNodes(Object context, org.dom4j.XPath sortXPath) { - List answer = selectNodes(context); + public List selectNodes(Object context, org.dom4j.XPath sortXPath) { + List answer = selectNodes(context); sortXPath.sort(answer); return answer; } - public List selectNodes(Object context, org.dom4j.XPath sortXPath, + public List selectNodes(Object context, org.dom4j.XPath sortXPath, boolean distinct) { - List answer = selectNodes(context); + List answer = selectNodes(context); sortXPath.sort(answer, distinct); return answer; @@ -221,7 +221,7 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { * @param list * is the list of Nodes to sort */ - public void sort(List list) { + public void sort(List list) { sort(list, false); } @@ -237,19 +237,14 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { * if true then duplicate values (using the sortXPath for * comparisions) will be removed from the List */ - public void sort(List list, boolean distinct) { + public void sort(List list, boolean distinct) { if ((list != null) && !list.isEmpty()) { int size = list.size(); - HashMap sortValues = new HashMap(size); + HashMap sortValues = new HashMap(size); - for (int i = 0; i < size; i++) { - Object object = list.get(i); - - if (object instanceof Node) { - Node node = (Node) object; - Object expression = getCompareValue(node); - sortValues.put(node, expression); - } + for (Node node : list) { + Object expression = getCompareValue(node); + sortValues.put(node, expression); } sort(list, sortValues); @@ -264,13 +259,13 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { try { setNSContext(node); - List answer = xpath.selectNodes(node); + List answer = xpath.selectNodes(node); if ((answer != null) && (answer.size() > 0)) { Object item = answer.get(0); if (item instanceof Boolean) { - return ((Boolean) item).booleanValue(); + return (Boolean) item; } return answer.contains(node); @@ -292,16 +287,16 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { * @param sortValues * DOCUMENT ME! */ - protected void sort(List list, final Map sortValues) { - Collections.sort(list, new Comparator() { - public int compare(Object o1, Object o2) { - o1 = sortValues.get(o1); - o2 = sortValues.get(o2); + protected void sort(List list, final Map sortValues) { + Collections.sort(list, new Comparator() { + public int compare(Node n1, Node n2) { + Object o1 = sortValues.get(n1); + Object o2 = sortValues.get(n2); if (o1 == o2) { return 0; } else if (o1 instanceof Comparable) { - Comparable c1 = (Comparable) o1; + Comparable c1 = (Comparable) o1; return c1.compareTo(o2); } else if (o1 == null) { @@ -325,12 +320,12 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { * @param sortValues * DOCUMENT ME! */ - protected void removeDuplicates(List list, Map sortValues) { + protected void removeDuplicates(List list, Map sortValues) { // remove distinct - HashSet distinctValues = new HashSet(); + HashSet distinctValues = new HashSet(); - for (Iterator iter = list.iterator(); iter.hasNext();) { - Object node = iter.next(); + for (Iterator iter = list.iterator(); iter.hasNext();) { + Node node = iter.next(); Object value = sortValues.get(node); if (distinctValues.contains(value)) { @@ -358,9 +353,10 @@ public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { return new Dom4jXPath(text); } catch (JaxenException e) { throw new InvalidXPathException(text, e.getMessage()); - } catch (Throwable t) { - throw new InvalidXPathException(text, t); + } catch (RuntimeException e) { } + + throw new InvalidXPathException(text); } protected void setNSContext(Object context) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpath/XPathPattern.java b/fine-org-dom4j/src/main/java/org/dom4j/xpath/XPathPattern.java index 1309f0935..65d656b0c 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/xpath/XPathPattern.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/xpath/XPathPattern.java @@ -8,6 +8,7 @@ package org.dom4j.xpath; import java.util.ArrayList; +import java.util.Collections; import org.dom4j.InvalidXPathException; import org.dom4j.Node; @@ -32,7 +33,7 @@ import org.jaxen.saxpath.SAXPathException; *

* * @author James Strachan - * @version $Revision$ + * @version $Revision: 1.18 $ */ public class XPathPattern implements org.dom4j.rule.Pattern { private String text; @@ -55,16 +56,14 @@ public class XPathPattern implements org.dom4j.rule.Pattern { this.pattern = PatternParser.parse(text); } catch (SAXPathException e) { throw new InvalidXPathException(text, e.getMessage()); - } catch (Throwable t) { - throw new InvalidXPathException(text, t); + } catch (RuntimeException e) { + throw new InvalidXPathException(text); } } public boolean matches(Node node) { try { - ArrayList list = new ArrayList(1); - list.add(node); - context.setNodeSet(list); + context.setNodeSet(Collections.singletonList(node)); return pattern.matches(node, context); } catch (JaxenException e) { diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpath/overview.html b/fine-org-dom4j/src/main/java/org/dom4j/xpath/overview.html deleted file mode 100644 index ca9c24475..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/xpath/overview.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -

This XPath implementation attempts to be a fully-compliant implementation of the -W3C XPath specification. -

- - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpath/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/xpath/package-info.java new file mode 100644 index 000000000..dda72ea6f --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/xpath/package-info.java @@ -0,0 +1,6 @@ +/** + * Provides the core tools needed to use the XPath library + *

+ * This XPath implementation attempts to be a fully-compliant implementation of the W3C XPath specification. + */ +package org.dom4j.xpath; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpath/package.html b/fine-org-dom4j/src/main/java/org/dom4j/xpath/package.html deleted file mode 100644 index 65671226c..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/xpath/package.html +++ /dev/null @@ -1,13 +0,0 @@ - - -org.dom4j.xpath :: package.html - - - - -

Provides the core tools needed to use the XPath library -

- - - - diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpp/ProxyXmlStartTag.java b/fine-org-dom4j/src/main/java/org/dom4j/xpp/ProxyXmlStartTag.java index 10f30abf9..11bd79385 100644 --- a/fine-org-dom4j/src/main/java/org/dom4j/xpp/ProxyXmlStartTag.java +++ b/fine-org-dom4j/src/main/java/org/dom4j/xpp/ProxyXmlStartTag.java @@ -20,12 +20,13 @@ import org.gjt.xpp.XmlPullParserException; import org.gjt.xpp.XmlStartTag; /** - * ProxyXmlStartTag implements the XPP XmlSmartTag - * interface while creating a dom4j Element underneath. - * - * @author James Strachan - * @author Maarten Coene - * @author Wolfgang Baer + *

+ * ProxyXmlStartTag implements the XPP XmlSmartTag interface + * while creating a dom4j Element underneath. + *

+ * + * @author James Strachan + * @version $Revision: 1.8 $ */ public class ProxyXmlStartTag implements XmlStartTag { /** The element being constructed */ @@ -117,8 +118,8 @@ public class ProxyXmlStartTag implements XmlStartTag { public String getAttributeValueFromRawName(String rawName) { if (element != null) { - for (Iterator iter = element.attributeIterator(); iter.hasNext();) { - Attribute attribute = (Attribute) iter.next(); + for (Iterator iter = element.attributeIterator(); iter.hasNext();) { + Attribute attribute = iter.next(); if (rawName.equals(attribute.getQualifiedName())) { return attribute.getValue(); @@ -132,8 +133,8 @@ public class ProxyXmlStartTag implements XmlStartTag { public String getAttributeValueFromName(String namespaceURI, String localName) { if (element != null) { - for (Iterator iter = element.attributeIterator(); iter.hasNext();) { - Attribute attribute = (Attribute) iter.next(); + for (Iterator iter = element.attributeIterator(); iter.hasNext();) { + Attribute attribute = iter.next(); if (namespaceURI.equals(attribute.getNamespaceURI()) && localName.equals(attribute.getName())) { @@ -159,13 +160,18 @@ public class ProxyXmlStartTag implements XmlStartTag { /** * parameters modeled after SAX2 attribute approach - * - * @param namespaceURI DOCUMENT ME! - * @param localName DOCUMENT ME! - * @param rawName DOCUMENT ME! - * @param value DOCUMENT ME! - * - * @throws XmlPullParserException DOCUMENT ME! + * + * @param namespaceURI + * DOCUMENT ME! + * @param localName + * DOCUMENT ME! + * @param rawName + * DOCUMENT ME! + * @param value + * DOCUMENT ME! + * + * @throws XmlPullParserException + * DOCUMENT ME! */ public void addAttribute(String namespaceURI, String localName, String rawName, String value) throws XmlPullParserException { @@ -199,15 +205,23 @@ public class ProxyXmlStartTag implements XmlStartTag { } } - /** - * Remove all atributes. - * - * @deprecated Use {@link #removeAttributes()} instead. - */ - public void removeAtttributes() throws XmlPullParserException { - removeAttributes(); + @Override + public boolean removeAttributeByName(String s, String s1) throws XmlPullParserException { + throw new UnsupportedOperationException(); } + @Override + public boolean removeAttributeByRawName(String s) throws XmlPullParserException { + throw new UnsupportedOperationException(); + } + + /** + * remove all atribute + * + * @throws XmlPullParserException + * DOCUMENT ME! + */ + @Override public void removeAttributes() throws XmlPullParserException { if (element != null) { element.setAttributes(new ArrayList()); @@ -242,33 +256,6 @@ public class ProxyXmlStartTag implements XmlStartTag { this.element = null; } - public boolean removeAttributeByName(String namespaceURI, String localName) - throws XmlPullParserException { - if (element != null) { - QName qname = QName.get(localName, namespaceURI); - Attribute attribute = element.attribute(qname); - return element.remove(attribute); - } - return false; - } - - public boolean removeAttributeByRawName(String rawName) - throws XmlPullParserException { - if (element != null) { - Attribute attribute = null; - Iterator it = element.attributeIterator(); - while (it.hasNext()) { - Attribute current = (Attribute) it.next(); - if (current.getQualifiedName().equals(rawName)) { - attribute = current; - break; - } - } - return element.remove(attribute); - } - return false; - } - // Properties // ------------------------------------------------------------------------- public DocumentFactory getDocumentFactory() { @@ -288,24 +275,24 @@ public class ProxyXmlStartTag implements XmlStartTag { * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided that the * following conditions are met: - * + * * 1. Redistributions of source code must retain copyright statements and * notices. Redistributions must also contain a copy of this document. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. The name "DOM4J" must not be used to endorse or promote products derived * from this Software without prior written permission of MetaStuff, Ltd. For * written permission, please contact dom4j-info@metastuff.com. - * + * * 4. Products derived from this Software may not be called "DOM4J" nor may * "DOM4J" appear in their names without prior written permission of MetaStuff, * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * + * * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * + * * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -317,6 +304,6 @@ public class ProxyXmlStartTag implements XmlStartTag { * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. */ diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpp/package-info.java b/fine-org-dom4j/src/main/java/org/dom4j/xpp/package-info.java new file mode 100644 index 000000000..93e59822d --- /dev/null +++ b/fine-org-dom4j/src/main/java/org/dom4j/xpp/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides implementation classes to cleanly integrate dom4j with the XML Pull Parser XPP. + */ +package org.dom4j.xpp; \ No newline at end of file diff --git a/fine-org-dom4j/src/main/java/org/dom4j/xpp/package.html b/fine-org-dom4j/src/main/java/org/dom4j/xpp/package.html deleted file mode 100644 index 1bcd92a3c..000000000 --- a/fine-org-dom4j/src/main/java/org/dom4j/xpp/package.html +++ /dev/null @@ -1,14 +0,0 @@ - - -org.dom4j.xpp :: package.html - - - - -

Provides implementation classes to cleanly integrate dom4j with the XML Pull Parser -XPP -

- - - - From d81318655cd00600e2a2c0feb4b6a21db54d1832 Mon Sep 17 00:00:00 2001 From: "Yuan.Wang" <1536296691@qq.com> Date: Fri, 9 Jun 2023 17:32:41 +0800 Subject: [PATCH 5/5] =?UTF-8?q?REPORT-95630=20batik=20=E5=8D=87=E5=88=B01.?= =?UTF-8?q?16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fine-xmlgraphics/xmlgraphics-batik/README.md | 2 +- .../xerces/impl/msg/DOMMessages.properties | 2 +- .../apache/batik/apps/rasterizer/Main.java | 6 +- .../DefaultExternalResourceSecurity.java | 10 ++ .../batik/bridge/DefaultScriptSecurity.java | 8 +- .../batik/bridge/SVGImageElementBridge.java | 32 ++-- .../svg12/XPathPatternContentSelector.java | 65 +++----- .../apache/batik/dom/AbstractDocument.java | 134 ++++------------- .../batik/script/rhino/RhinoClassShutter.java | 8 + .../src/main/resources/NOTICE | 2 +- .../bridge/resources/Messages.properties | 140 ++++++++++++++++++ .../apache/batik/bridge/resources/help.gif | Bin 0 -> 947 bytes .../apache/batik/bridge/resources/move.gif | Bin 0 -> 930 bytes 13 files changed, 236 insertions(+), 173 deletions(-) create mode 100644 fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/Messages.properties create mode 100644 fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/help.gif create mode 100644 fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/move.gif diff --git a/fine-xmlgraphics/xmlgraphics-batik/README.md b/fine-xmlgraphics/xmlgraphics-batik/README.md index e96552704..d7301f037 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/README.md +++ b/fine-xmlgraphics/xmlgraphics-batik/README.md @@ -1,2 +1,2 @@ 源码地址:https://github.com/apache/xmlgraphics-batik
-版本:1.14 \ No newline at end of file +版本:1.16 \ No newline at end of file diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/com/sun/xml/stream/xerces/impl/msg/DOMMessages.properties b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/com/sun/xml/stream/xerces/impl/msg/DOMMessages.properties index 95ea285e2..2a7e6b5d1 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/com/sun/xml/stream/xerces/impl/msg/DOMMessages.properties +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/com/sun/xml/stream/xerces/impl/msg/DOMMessages.properties @@ -13,7 +13,7 @@ # exception codes DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString. HIERARCHY_REQUEST_ERR = An attempt was made to insert a node where it is not permitted. -INDEX_SIZE_ERR = The index or size is negative, or greater than the allowed value. +INDEX_SIZE_ERR = The indexs or size is negative, or greater than the allowed value. INUSE_ATTRIBUTE_ERR = An attempt is made to add an attribute that is already in use elsewhere. INVALID_ACCESS_ERR = A parameter or an operation is not supported by the underlying object. INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified. diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/apps/rasterizer/Main.java b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/apps/rasterizer/Main.java index a4248b527..a42f3e3cd 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/apps/rasterizer/Main.java +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/apps/rasterizer/Main.java @@ -934,8 +934,10 @@ public class Main implements SVGConverterController { ApplicationSecurityEnforcer securityEnforcer = new ApplicationSecurityEnforcer(this.getClass(), RASTERIZER_SECURITY_POLICY); - - securityEnforcer.enforceSecurity(!c.getSecurityOff()); + try { + securityEnforcer.enforceSecurity(!c.getSecurityOff()); + } catch (UnsupportedOperationException e) { + } String[] expandedSources = expandSources(sources); diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultExternalResourceSecurity.java b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultExternalResourceSecurity.java index a9e5d8828..8279a9a98 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultExternalResourceSecurity.java +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultExternalResourceSecurity.java @@ -20,6 +20,9 @@ package org.apache.batik.bridge; import org.apache.batik.util.ParsedURL; +import java.net.URI; +import java.net.URISyntaxException; + /** * Default implementation for the ExternalResourceSecurity interface. * It allows all types of external resources to be loaded, but only if they @@ -81,6 +84,13 @@ public class DefaultExternalResourceSecurity implements ExternalResourceSecurity } else { String docHost = docURL.getHost(); String externalResourceHost = externalResourceURL.getHost(); + if (externalResourceHost == null && !DATA_PROTOCOL.equals(externalResourceURL.getProtocol())) { + try { + externalResourceHost = new URI(externalResourceURL.getPath()).getHost(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } if ((docHost != externalResourceHost) && ((docHost == null) || (!docHost.equals(externalResourceHost)))){ diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultScriptSecurity.java b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultScriptSecurity.java index e64c29c9c..bf30c08bb 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultScriptSecurity.java +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/DefaultScriptSecurity.java @@ -20,6 +20,8 @@ package org.apache.batik.bridge; import org.apache.batik.util.ParsedURL; +import static org.apache.batik.util.SVGConstants.SVG_SCRIPT_TYPE_JAVA; + /** * Default implementation for the ScriptSecurity interface. * It allows all types of scripts to be loaded, but only if they @@ -76,13 +78,17 @@ public class DefaultScriptSecurity implements ScriptSecurity { ParsedURL docURL){ // Make sure that the archives comes from the same host // as the document itself - if (docURL == null) { + if (docURL == null || SVG_SCRIPT_TYPE_JAVA.equals(scriptType)) { se = new SecurityException (Messages.formatMessage(ERROR_CANNOT_ACCESS_DOCUMENT_URL, new Object[]{scriptURL})); } else { String docHost = docURL.getHost(); String scriptHost = scriptURL.getHost(); + + if (scriptHost == null && scriptURL.getPath() != null) { + scriptHost = new ParsedURL(scriptURL.getPath()).getHost(); + } if ((docHost != scriptHost) && ((docHost == null) || (!docHost.equals(scriptHost)))) { diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/SVGImageElementBridge.java b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/SVGImageElementBridge.java index a4f76534e..ee25c23b7 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/SVGImageElementBridge.java +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/SVGImageElementBridge.java @@ -175,33 +175,33 @@ public class SVGImageElementBridge extends AbstractGraphicsNodeBridge { } else { purl = new ParsedURL(baseURI, uriStr); } - + checkLoadExternalResource(ctx, e, purl); return createImageGraphicsNode(ctx, e, purl); } - protected GraphicsNode createImageGraphicsNode(BridgeContext ctx, - Element e, - ParsedURL purl) { - Rectangle2D bounds = getImageBounds(ctx, e); - if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) { - ShapeNode sn = new ShapeNode(); - sn.setShape(bounds); - return sn; - } - + private void checkLoadExternalResource(BridgeContext ctx, Element e, ParsedURL purl) { SVGDocument svgDoc = (SVGDocument)e.getOwnerDocument(); String docURL = svgDoc.getURL(); ParsedURL pDocURL = null; - if (docURL != null) + if (docURL != null) { pDocURL = new ParsedURL(docURL); - + } UserAgent userAgent = ctx.getUserAgent(); - try { userAgent.checkLoadExternalResource(purl, pDocURL); } catch (SecurityException secEx ) { - throw new BridgeException(ctx, e, secEx, ERR_URI_UNSECURE, - new Object[] {purl}); + throw new BridgeException(ctx, e, secEx, ERR_URI_UNSECURE, new Object[] {purl}); + } + } + + protected GraphicsNode createImageGraphicsNode(BridgeContext ctx, + Element e, + ParsedURL purl) { + Rectangle2D bounds = getImageBounds(ctx, e); + if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) { + ShapeNode sn = new ShapeNode(); + sn.setShape(bounds); + return sn; } DocumentLoader loader = ctx.getDocumentLoader(); diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/svg12/XPathPatternContentSelector.java b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/svg12/XPathPatternContentSelector.java index b72f723a4..4e76ca879 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/svg12/XPathPatternContentSelector.java +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/bridge/svg12/XPathPatternContentSelector.java @@ -18,20 +18,22 @@ */ package org.apache.batik.bridge.svg12; -import java.util.ArrayList; - -import org.apache.xml.utils.PrefixResolver; -import org.apache.xpath.XPath; -import org.apache.xpath.XPathContext; - import org.apache.batik.anim.dom.XBLOMContentElement; import org.apache.batik.dom.AbstractDocument; - import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.xpath.XPathException; +import javax.xml.namespace.NamespaceContext; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.util.ArrayList; +import java.util.Iterator; + /** * A class to handle the XPath Pattern syntax for XBL content elements. * @@ -48,12 +50,7 @@ public class XPathPatternContentSelector extends AbstractContentSelector { /** * The XPath expression. */ - protected XPath xpath; - - /** - * The XPath context. - */ - protected XPathContext context; + protected XPathExpression xpath; /** * The selected nodes. @@ -81,10 +78,11 @@ public class XPathPatternContentSelector extends AbstractContentSelector { * Parses the XPath selector. */ protected void parse() { - context = new XPathContext(); try { - xpath = new XPath(expression, null, prefixResolver, XPath.MATCH); - } catch (javax.xml.transform.TransformerException te) { + XPath xPathAPI = XPathFactory.newInstance().newXPath(); + xPathAPI.setNamespaceContext(prefixResolver); + xpath = xPathAPI.compile(expression); + } catch (XPathExpressionException te) { AbstractDocument doc = (AbstractDocument) contentElement.getOwnerDocument(); throw doc.createXPathException @@ -173,9 +171,8 @@ public class XPathPatternContentSelector extends AbstractContentSelector { protected void update(Node n) { if (!isSelected(n)) { try { - double matchScore - = xpath.execute(context, n, prefixResolver).num(); - if (matchScore != XPath.MATCH_SCORE_NONE) { + Double matchScore = (Double) xpath.evaluate(n, XPathConstants.NUMBER); + if (matchScore != null) { if (!descendantSelected(n)) { nodes.add(n); } @@ -186,7 +183,7 @@ public class XPathPatternContentSelector extends AbstractContentSelector { n = n.getNextSibling(); } } - } catch (javax.xml.transform.TransformerException te) { + } catch (XPathExpressionException te) { AbstractDocument doc = (AbstractDocument) contentElement.getOwnerDocument(); throw doc.createXPathException @@ -217,36 +214,20 @@ public class XPathPatternContentSelector extends AbstractContentSelector { /** * Xalan prefix resolver. */ - protected class NSPrefixResolver implements PrefixResolver { - - /** - * Get the base URI for this resolver. Since this resolver isn't - * associated with a particular node, returns null. - */ - public String getBaseIdentifier() { - return null; - } - + protected class NSPrefixResolver implements NamespaceContext { /** * Resolves the given namespace prefix. */ - public String getNamespaceForPrefix(String prefix) { + public String getNamespaceURI(String prefix) { return contentElement.lookupNamespaceURI(prefix); } - /** - * Resolves the given namespace prefix. - */ - public String getNamespaceForPrefix(String prefix, Node context) { - // ignore the context node - return contentElement.lookupNamespaceURI(prefix); + public String getPrefix(String namespaceURI) { + return null; } - /** - * Returns whether this PrefixResolver handles a null prefix. - */ - public boolean handlesNullPrefixes() { - return false; + public Iterator getPrefixes(String namespaceURI) { + return null; } } } diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/dom/AbstractDocument.java b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/dom/AbstractDocument.java index 35d586836..31319eb83 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/dom/AbstractDocument.java +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/dom/AbstractDocument.java @@ -45,12 +45,6 @@ import org.apache.batik.util.DOMConstants; import org.apache.batik.util.SoftDoublyIndexedTable; import org.apache.batik.constants.XMLConstants; -import org.apache.xml.utils.PrefixResolver; - -import org.apache.xpath.XPath; -import org.apache.xpath.XPathContext; -import org.apache.xpath.objects.XObject; - import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.DocumentType; @@ -79,6 +73,13 @@ import org.w3c.dom.xpath.XPathExpression; import org.w3c.dom.xpath.XPathNSResolver; import org.w3c.dom.xpath.XPathResult; +import javax.xml.namespace.NamespaceContext; +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + /** * This class implements the {@link org.w3c.dom.Document} interface. * @@ -2177,7 +2178,7 @@ public abstract class AbstractDocument /** * The compiled XPath expression. */ - protected XPath xpath; + protected javax.xml.xpath.XPathExpression xpath; /** * The namespace resolver. @@ -2189,11 +2190,6 @@ public abstract class AbstractDocument */ protected NSPrefixResolver prefixResolver; - /** - * The XPathContext object. - */ - protected XPathContext context; - /** * Creates a new XPathExpr object. */ @@ -2202,9 +2198,10 @@ public abstract class AbstractDocument resolver = res; prefixResolver = new NSPrefixResolver(); try { - xpath = new XPath(expr, null, prefixResolver, XPath.SELECT); - context = new XPathContext(); - } catch (javax.xml.transform.TransformerException te) { + XPath xPathAPI = XPathFactory.newInstance().newXPath(); + xPathAPI.setNamespaceContext(prefixResolver); + xpath = xPathAPI.compile(expr); + } catch (XPathExpressionException te) { throw createXPathException (XPathException.INVALID_EXPRESSION_ERR, "xpath.invalid.expression", @@ -2245,48 +2242,25 @@ public abstract class AbstractDocument new Object[] {(int) contextNode.getNodeType(), contextNode.getNodeName() }); } - context.reset(); - XObject result = null; - try { - result = xpath.execute(context, contextNode, prefixResolver); - } catch (javax.xml.transform.TransformerException te) { - throw createXPathException - (XPathException.INVALID_EXPRESSION_ERR, - "xpath.error", - new Object[] { xpath.getPatternString(), - te.getMessage() }); - } + try { switch (type) { case XPathResult.ANY_UNORDERED_NODE_TYPE: case XPathResult.FIRST_ORDERED_NODE_TYPE: - return convertSingleNode(result, type); + return new Result((Node) xpath.evaluate(contextNode, XPathConstants.NODE), type); case XPathResult.BOOLEAN_TYPE: - return convertBoolean(result); + return new Result((Boolean) xpath.evaluate(contextNode, XPathConstants.BOOLEAN)); case XPathResult.NUMBER_TYPE: - return convertNumber(result); + return new Result((Double) xpath.evaluate(contextNode, XPathConstants.NUMBER)); case XPathResult.ORDERED_NODE_ITERATOR_TYPE: case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE: case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE: - return convertNodeIterator(result, type); + return new Result((Node) xpath.evaluate(contextNode, XPathConstants.NODE), type); case XPathResult.STRING_TYPE: - return convertString(result); - case XPathResult.ANY_TYPE: - switch (result.getType()) { - case XObject.CLASS_BOOLEAN: - return convertBoolean(result); - case XObject.CLASS_NUMBER: - return convertNumber(result); - case XObject.CLASS_STRING: - return convertString(result); - case XObject.CLASS_NODESET: - return convertNodeIterator - (result, - XPathResult.UNORDERED_NODE_ITERATOR_TYPE); - } + return new Result((String) xpath.evaluate(contextNode, XPathConstants.STRING)); } - } catch (javax.xml.transform.TransformerException te) { + } catch (XPathExpressionException | TransformerException te) { throw createXPathException (XPathException.TYPE_ERR, "xpath.cannot.convert.result", @@ -2296,45 +2270,6 @@ public abstract class AbstractDocument return null; } - /** - * Converts an XObject to a single node XPathResult. - */ - protected Result convertSingleNode(XObject xo, short type) - throws javax.xml.transform.TransformerException { - return new Result(xo.nodelist().item(0), type); - } - - /** - * Converts an XObject to a boolean XPathResult. - */ - protected Result convertBoolean(XObject xo) - throws javax.xml.transform.TransformerException { - return new Result(xo.bool()); - } - - /** - * Converts an XObject to a number XPathResult. - */ - protected Result convertNumber(XObject xo) - throws javax.xml.transform.TransformerException { - return new Result(xo.num()); - } - - /** - * Converts an XObject to a string XPathResult. - */ - protected Result convertString(XObject xo) { - return new Result(xo.str()); - } - - /** - * Converts an XObject to a node iterator XPathResult. - */ - protected Result convertNodeIterator(XObject xo, short type) - throws javax.xml.transform.TransformerException { - return new Result(xo.nodelist(), type); - } - /** * XPathResult implementation. * XXX Namespace nodes are not handled correctly, since Xalan returns @@ -2537,42 +2472,23 @@ public abstract class AbstractDocument /** * Xalan prefix resolver. */ - protected class NSPrefixResolver implements PrefixResolver { - - /** - * Get the base URI for this resolver. Since this resolver isn't - * associated with a particular node, returns null. - */ - public String getBaseIdentifier() { - return null; - } - + protected class NSPrefixResolver implements NamespaceContext { /** * Resolves the given namespace prefix. */ - public String getNamespaceForPrefix(String prefix) { + public String getNamespaceURI(String prefix) { if (resolver == null) { return null; } return resolver.lookupNamespaceURI(prefix); } - /** - * Resolves the given namespace prefix. - */ - public String getNamespaceForPrefix(String prefix, Node context) { - // ignore the context node - if (resolver == null) { - return null; - } - return resolver.lookupNamespaceURI(prefix); + public String getPrefix(String namespaceURI) { + return null; } - /** - * Returns whether this PrefixResolver handles a null prefix. - */ - public boolean handlesNullPrefixes() { - return false; + public Iterator getPrefixes(String namespaceURI) { + return null; } } } diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/script/rhino/RhinoClassShutter.java b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/script/rhino/RhinoClassShutter.java index f6524f6c0..307affae6 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/script/rhino/RhinoClassShutter.java +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/java/org/apache/batik/script/rhino/RhinoClassShutter.java @@ -20,6 +20,9 @@ package org.apache.batik.script.rhino; import org.mozilla.javascript.ClassShutter; +import java.util.Arrays; +import java.util.List; + /** * Class shutter that restricts access to Batik internals from script. * @@ -27,6 +30,7 @@ import org.mozilla.javascript.ClassShutter; * @version $Id$ */ public class RhinoClassShutter implements ClassShutter { + private static final List WHITELIST = Arrays.asList("java.io.PrintStream", "java.lang.System", "java.net.URL"); /* public RhinoClassShutter() { @@ -55,6 +59,10 @@ public class RhinoClassShutter implements ClassShutter { * Returns whether the given class is visible to scripts. */ public boolean visibleToScripts(String fullClassName) { + if (!WHITELIST.contains(fullClassName) && !fullClassName.endsWith("Permission") && !fullClassName.startsWith("org.")) { + return false; + } + // Don't let them mess with script engine's internals. if (fullClassName.startsWith("org.mozilla.javascript")) return false; diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/NOTICE b/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/NOTICE index 146dcd046..d794a759a 100644 --- a/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/NOTICE +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/NOTICE @@ -1,5 +1,5 @@ Apache Batik -Copyright 1999-2020 The Apache Software Foundation +Copyright 1999-2022 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/Messages.properties b/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/Messages.properties new file mode 100644 index 000000000..5e8b22de4 --- /dev/null +++ b/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/Messages.properties @@ -0,0 +1,140 @@ +# ----------------------------------------------------------------------------- +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# $Id$ +# ----------------------------------------------------------------------------- + +attribute.missing = \ +{0}:{1}\n\ +The attribute "{3}" of the element <{2}> is required + +attribute.malformed = \ +{0}:{1}\n\ +The attribute "{3}" of the element <{2}> is invalid + +attribute.not.animatable = \ +{0}:{1}\n\ +The attribute "{4}" of the element <{3}> is not animatable + +type.not.animatable = \ +{0}:{1}\n\ +The attribute "{4}" of the element <{3}> cannot be animated with the \ +<{5}> element + +length.negative = \ +{0}:{1}\n\ +The attribute "{3}" of the element <{2}> cannot be negative + +css.length.negative = \ +{0}:{1}\n\ +The CSS property "{3}" found on the element <{2}> cannot be negative + +css.uri.badTarget = \ +{0}:{1}\n\ +The URI "{3}"\n\ +for a CSS property found on the element <{2}> is invalid + +xlink.href.circularDependencies = \ +{0}:{1}\n\ +A circular dependency has been detected on the element <{2}> for the URI:\n\ +"{3}" + +uri.malformed = \ +{0}:{1}\n\ +The URI "{3}"\n\ +specified on the element <{2}> is invalid + +uri.badTarget = \ +{0}:{1}\n\ +Cannot find the referenced element:\n\ +"{3}"\n\ +specified on the element <{2}> - may be a problem of ''id'' + +uri.io = \ +{0}:{1}\n\ +An I/O error occured while processing the URI:\n\ +"{3}"\n\ +specified on the element <{2}> + +uri.unsecure = \ +{0}:{1}\n\ +A security exception occured while processing the URI:\n\ +"{3}"\n\ +specified on the element <{2}> + +uri.referenceDocument = \ +{0}:{1}\n\ +The URI "{3}"\n\ +specified on the element <{2}> references an entire document. \n\ +This is illegal: The element <{2}> must reference an element\n\ +inside a document. + +uri.image.invalid = \ +{0}:{1}\n\ +The URI "{3}"\n\ +specified on the element <{2}> is invalid + +uri.image.broken = \ +{0}:{1}\n\ +The URI "{3}"\n\ +on element <{2}> can''t be opened because:\n\ +{4} + +uri.image.error = \ +The URI can''t be opened:\n\ +{0} + +########################################################################## +# Messages for DefaultScriptSecurity +########################################################################## + +DefaultScriptSecurity.error.cannot.access.document.url = \ +Could not access the current document URL when trying to load script file {0}. Script will not be loaded as it is not possible to verify it comes from the same location as the document. + +DefaultScriptSecurity.error.script.from.different.url = \ +The document references a script file ({0}) which comes from different location than the document itself. This is not allowed with the current security settings and that script will not be loaded. + +EmbededScriptSecurity.error.script.not.embeded = \ +The document references a script file ({0}) which is not embeded in the document. This is not allowed with the current security settings and that script will not be loaded. + +EmbededExternalResourceSecurity.error.external.resource.not.embeded = \ +The document references a resource ({0}) which is not embeded in the document. This is not allowed with the current security settings and that resource cannot be loaded. + +NoLoadScriptSecurity.error.no.script.of.type.allowed = \ +Scripts of type ({0}) cannot be loaded and executed with the current security settings. + +DefaultExternalResourceSecurity.error.cannot.access.document.url = \ +Could not access the current document URL when trying to load an external resource {0}. The external resource will not be loaded as it is not possible to verify it comes from the same location as the document. + +DefaultExternalResourceSecurity.error.external.resource.from.different.url = \ +The document references a external resource ({0}) which comes from different location than the document itself. This is not allowed for security reasons and that resource will not be loaded. + +NoLoadExternalResourceSecurity.error.no.external.resource.allowed = \ +The security settings do not allow any external resources to be referenced from the document + +########################################################################## +# Messages for BaseScriptingEnvironment +########################################################################## + +BaseScriptingEnvironment.constant.inline.script.description = \ +Inline {1} {0}:{2} + +BaseScriptingEnvironment.constant.event.script.description = \ +Event attribute {0}:{2} {1} + +SVG12ScriptingEnvironment.constant.handler.script.description = \ +Handler {0}:{3} {1} {2} diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/help.gif b/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/help.gif new file mode 100644 index 0000000000000000000000000000000000000000..6a5de8cb88b5523600f633fca282df85dd0217f9 GIT binary patch literal 947 zcmV;k15Er!Nk%w1VHN-u0Ou$G000010RaL60s{jB1Ox;H1qB8M1_uWR2nYxX2?+`c z3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^sIZa%Ew3Wn>_CX>@2HRA^-&M@dak03rDV0SW;A04x9i000&M761SU zcK`wS8%VIA!Giz<9$bjy6hqp)Y49XPm<~6xH0g0=&zTx8cEm~ZC`Y3VDH4sDlj+ot60QEE V+B9lXu3nvn9ZR;XS+W5E06U)m!sP$} literal 0 HcmV?d00001 diff --git a/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/move.gif b/fine-xmlgraphics/xmlgraphics-batik/src/main/resources/org/org/apache/batik/bridge/resources/move.gif new file mode 100644 index 0000000000000000000000000000000000000000..90bb091bc4a5b5fc21beedf87f0c24ef71cca3e7 GIT binary patch literal 930 zcmV;T16}+_Nk%w1VHf}y0Ou$G000010RaL60s{jB1Ox;H1qB8M1_uWR2nYxX2?+`c z3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^sIZa%Ew3Wn>_CX>@2HRA^-&M@dak03rDV0SW;A04x9i000;O7ytkW zW&r&O97wRB!Gj1BDqP60p+kZH{yjAK4*&p(6Cql(i1A^?jT}Ati^x%8M}-wlhD^Ee zV?>uEFDCp5vgXE<1Zmo=i8E(Om@Zq&49b$BNth!&+UzOxW=4%NpF(6RwW`&tPXht~ EJ0@1U6951J literal 0 HcmV?d00001