From de3e0a1d9e95c5b9bf5ebc5ad8c64b57387039d7 Mon Sep 17 00:00:00 2001 From: hzzz Date: Tue, 5 Jun 2018 23:24:06 +0800 Subject: [PATCH 1/2] fix --- build.third_step1.gradle | 2 + .../lib/javax.servlet-api-3.0.1.jar | Bin 0 -> 85353 bytes .../fileupload/portlet/PortletFileUpload.java | 2 +- .../portlet/PortletRequestContext.java | 2 +- .../servlet/FileCleanerCleanup.java | 2 +- fine-spring/fine-spring.iml | 7 + fine-spring/lib/commons-logging-1.2.jar | Bin 0 -> 61829 bytes .../aop/aspectj/AspectJProxyFactory.java | 3 +- .../aop/aspectj/AspectMetadata.java | 7 +- .../BeanFactoryAspectInstanceFactory.java | 1 - .../BeanFactoryAspectJAdvisorsBuilder.java | 1 - ...ntiationModelAwarePointcutAdvisorImpl.java | 471 +++++++++--------- ...ngletonAspectInstanceFactoryDecorator.java | 1 - .../MetadataAwareAspectInstanceFactory.java | 3 +- ...pleMetadataAwareAspectInstanceFactory.java | 5 +- ...tonMetadataAwareAspectInstanceFactory.java | 1 - .../core/io/ContextResource.java | 2 +- .../web/bind/annotation/ExceptionHandler.java | 8 +- .../web/bind/annotation/RequestMapping.java | 8 +- .../request/FacesRequestAttributes.java | 2 +- .../web/context/request/NativeWebRequest.java | 16 +- .../commons/CommonsFileUploadSupport.java | 20 +- .../commons/CommonsMultipartFile.java | 8 +- .../commons/CommonsMultipartResolver.java | 18 +- 24 files changed, 292 insertions(+), 298 deletions(-) create mode 100644 fine-commons-fileupload/lib/javax.servlet-api-3.0.1.jar create mode 100644 fine-spring/lib/commons-logging-1.2.jar diff --git a/build.third_step1.gradle b/build.third_step1.gradle index ad905a76c..c429fd885 100644 --- a/build.third_step1.gradle +++ b/build.third_step1.gradle @@ -31,6 +31,7 @@ sourceSets{ "${srcDir}/fine-poi/src", "${srcDir}/fine-quartz/src", "${srcDir}/fine-commons-io/src", + "${srcDir}/fine-portlet-api/src", "${srcDir}/fine-commons-fileupload/src", "${srcDir}/fine-commons-lang3/src", "${srcDir}/fine-commons-collections4/src" @@ -78,6 +79,7 @@ task copyFiles(type:Copy,dependsOn:'compileJava'){ with dataContent.call("${srcDir}/fine-poi/src") with dataContent.call("${srcDir}/fine-quartz/src") with dataContent.call("${srcDir}/fine-commons-io/src") + with dataContent.call("${srcDir}/fine-portlet-api/src") with dataContent.call("${srcDir}/fine-commons-fileupload/src") into "${classesDir}" } diff --git a/fine-commons-fileupload/lib/javax.servlet-api-3.0.1.jar b/fine-commons-fileupload/lib/javax.servlet-api-3.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..4e2edcc9df69742be7b55e19370dddb5b20fc451 GIT binary patch literal 85353 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%0Ar@y{D-hY*!XHbeQp%zeE{JQy1 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 literal 0 HcmV?d00001 diff --git a/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java b/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java index d8cddda00..4202acee6 100755 --- a/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java +++ b/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java @@ -19,7 +19,7 @@ package com.fr.third.org.apache.commons.fileupload.portlet; import java.io.IOException; import java.util.List; -import javax.portlet.ActionRequest; +import com.fr.third.javax.portlet.ActionRequest; import com.fr.third.org.apache.commons.fileupload.FileItemFactory; import com.fr.third.org.apache.commons.fileupload.FileItemIterator; diff --git a/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java b/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java index d4cfd0a4e..d784994fc 100755 --- a/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java +++ b/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java @@ -18,7 +18,7 @@ package com.fr.third.org.apache.commons.fileupload.portlet; import java.io.InputStream; import java.io.IOException; -import javax.portlet.ActionRequest; +import com.fr.third.javax.portlet.ActionRequest; import com.fr.third.org.apache.commons.fileupload.RequestContext; /** diff --git a/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java b/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java index c1270a181..a545410ca 100755 --- a/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java +++ b/fine-commons-fileupload/src/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java @@ -24,7 +24,7 @@ import com.fr.third.org.apache.commons.io.FileCleaner; /** * A servlet context listener, which ensures that the - * {@link org.apache.commons.io.FileCleaner FileCleaner's} + * {@link com.fr.third.org.apache.commons.io.FileCleaner FileCleaner's} * reaper thread is terminated, * when the web application is destroyed. */ diff --git a/fine-spring/fine-spring.iml b/fine-spring/fine-spring.iml index f7a68fea2..13858cac5 100644 --- a/fine-spring/fine-spring.iml +++ b/fine-spring/fine-spring.iml @@ -8,5 +8,12 @@ + + + + + + + \ No newline at end of file diff --git a/fine-spring/lib/commons-logging-1.2.jar b/fine-spring/lib/commons-logging-1.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..93a3b9f6db406c84e270e19b9a5e70f2e27ca513 GIT binary patch literal 61829 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

?Qscg)P&$+povC*M;449{4wvf+Lu`*i$g8 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

6R?CS7jP_?OetFBKT#*D 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 Sa`OQ?z*ER31cwkn0N{V*NK-8U literal 0 HcmV?d00001 diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectJProxyFactory.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectJProxyFactory.java index 4981e8a5d..f86660b29 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectJProxyFactory.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectJProxyFactory.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import com.fr.third.aspectj.lang.annotation.AspectMetadata; import com.fr.third.aspectj.lang.reflect.PerClauseKind; import com.fr.third.springframework.aop.Advisor; @@ -91,7 +90,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport { public void addAspect(Object aspectInstance) { Class aspectClass = aspectInstance.getClass(); String aspectName = aspectClass.getName(); - com.fr.third.aspectj.lang.annotation.AspectMetadata am = createAspectMetadata(aspectClass, aspectName); + AspectMetadata am = createAspectMetadata(aspectClass, aspectName); if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) { throw new IllegalArgumentException( "Aspect class [" + aspectClass.getName() + "] does not define a singleton aspect"); diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectMetadata.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectMetadata.java index cdbbb5e63..4e7f3f0c9 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectMetadata.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/AspectMetadata.java @@ -14,17 +14,16 @@ * limitations under the License. */ -package com.fr.third.aspectj.lang.annotation; +package com.fr.third.springframework.aop.aspectj; import com.fr.third.aspectj.lang.reflect.AjType; import com.fr.third.aspectj.lang.reflect.AjTypeSystem; import com.fr.third.aspectj.lang.reflect.PerClauseKind; import com.fr.third.springframework.aop.Pointcut; -import com.fr.third.springframework.aop.aspectj.AspectJExpressionPointcut; -import com.fr.third.springframework.aop.aspectj.TypePatternClassFilter; import com.fr.third.springframework.aop.framework.AopConfigException; import com.fr.third.springframework.aop.support.ComposablePointcut; +import org.aspectj.lang.annotation.Aspect; /** * Metadata for an AspectJ aspect class, with an additional Spring AOP pointcut @@ -37,7 +36,7 @@ import com.fr.third.springframework.aop.support.ComposablePointcut; * @author Rod Johnson * @author Juergen Hoeller * @since 2.0 - * @see com.fr.third.aspectj.AspectJExpressionPointcut + * @see com.fr.third.springframework.aop.aspectj.AspectJExpressionPointcut */ public class AspectMetadata { diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectInstanceFactory.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectInstanceFactory.java index 461945967..92e214320 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectInstanceFactory.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectInstanceFactory.java @@ -16,7 +16,6 @@ package com.fr.third.springframework.aop.aspectj; -import com.fr.third.aspectj.lang.annotation.AspectMetadata; import com.fr.third.springframework.beans.factory.BeanFactory; import com.fr.third.springframework.beans.factory.config.ConfigurableBeanFactory; import com.fr.third.springframework.core.Ordered; diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectJAdvisorsBuilder.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectJAdvisorsBuilder.java index 11f00856f..065157935 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectJAdvisorsBuilder.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/BeanFactoryAspectJAdvisorsBuilder.java @@ -22,7 +22,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import com.fr.third.aspectj.lang.annotation.AspectMetadata; import com.fr.third.aspectj.lang.reflect.PerClauseKind; import com.fr.third.springframework.aop.Advisor; diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/InstantiationModelAwarePointcutAdvisorImpl.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/InstantiationModelAwarePointcutAdvisorImpl.java index 4d0653572..d18fc2da5 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/InstantiationModelAwarePointcutAdvisorImpl.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/InstantiationModelAwarePointcutAdvisorImpl.java @@ -16,256 +16,249 @@ package com.fr.third.springframework.aop.aspectj; -import java.lang.reflect.Method; - -import org.aopalliance.aop.Advice; import com.fr.third.aspectj.lang.reflect.PerClauseKind; - import com.fr.third.springframework.aop.Pointcut; import com.fr.third.springframework.aop.support.DynamicMethodMatcherPointcut; import com.fr.third.springframework.aop.support.Pointcuts; +import org.aopalliance.aop.Advice; -import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAfter; -import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAfterReturning; -import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAfterThrowing; -import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAround; -import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtPointcut; +import java.lang.reflect.Method; /** - * Internal implementation of AspectJPointcutAdvisor. - * Note that there will be one instance of this advisor for each target method. + * Internal implementation of AspectJPointcutAdvisor. Note that there will be one instance of this + * advisor for each target method. * * @author Rod Johnson * @author Juergen Hoeller * @since 2.0 */ class InstantiationModelAwarePointcutAdvisorImpl - implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation { - - private final AspectJExpressionPointcut declaredPointcut; - - private Pointcut pointcut; - - private final MetadataAwareAspectInstanceFactory aspectInstanceFactory; - - private final Method method; - - private final boolean lazy; - - private final AspectJAdvisorFactory atAspectJAdvisorFactory; - - private Advice instantiatedAdvice; - - private int declarationOrder; - - private String aspectName; - - private Boolean isBeforeAdvice; - - private Boolean isAfterAdvice; - - - public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp, - MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) { - - this.declaredPointcut = ajexp; - this.method = method; - this.atAspectJAdvisorFactory = af; - this.aspectInstanceFactory = aif; - this.declarationOrder = declarationOrderInAspect; - this.aspectName = aspectName; - - if (aif.getAspectMetadata().isLazilyInstantiated()) { - // Static part of the pointcut is a lazy type. - Pointcut preInstantiationPointcut = - Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); - - // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. - // If it's not a dynamic pointcut, it may be optimized out - // by the Spring AOP infrastructure after the first evaluation. - this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif); - this.lazy = true; - } - else { - // A singleton aspect. - this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); - this.pointcut = declaredPointcut; - this.lazy = false; - } - } - - - /** - * The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change - * depending on the state of the advice. - */ - @Override - public Pointcut getPointcut() { - return this.pointcut; - } - - /** - * This is only of interest for Spring AOP: AspectJ instantiation semantics - * are much richer. In AspectJ terminology, all a return of {@code true} - * means here is that the aspect is not a SINGLETON. - */ - @Override - public boolean isPerInstance() { - return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON); - } - - /** - * Return the AspectJ AspectMetadata for this advisor. - */ - public com.fr.third.aspectj.lang.annotation.AspectMetadata getAspectMetadata() { - return this.aspectInstanceFactory.getAspectMetadata(); - } - - /** - * Lazily instantiate advice if necessary. - */ - @Override - public synchronized Advice getAdvice() { - if (this.instantiatedAdvice == null) { - this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); - } - return this.instantiatedAdvice; - } - - @Override - public boolean isLazy() { - return this.lazy; - } - - @Override - public synchronized boolean isAdviceInstantiated() { - return (this.instantiatedAdvice != null); - } - - - private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { - return this.atAspectJAdvisorFactory.getAdvice( - this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); - } - - public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() { - return this.aspectInstanceFactory; - } - - public AspectJExpressionPointcut getDeclaredPointcut() { - return this.declaredPointcut; - } - - @Override - public int getOrder() { - return this.aspectInstanceFactory.getOrder(); - } - - @Override - public String getAspectName() { - return this.aspectName; - } - - @Override - public int getDeclarationOrder() { - return this.declarationOrder; - } - - @Override - public boolean isBeforeAdvice() { - if (this.isBeforeAdvice == null) { - determineAdviceType(); - } - return this.isBeforeAdvice; - } - - @Override - public boolean isAfterAdvice() { - if (this.isAfterAdvice == null) { - determineAdviceType(); - } - return this.isAfterAdvice; - } - - /** - * Duplicates some logic from getAdvice, but importantly does not force - * creation of the advice. - */ - private void determineAdviceType() { - AbstractAspectJAdvisorFactory.AspectJAnnotation aspectJAnnotation = - AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method); - if (aspectJAnnotation == null) { - this.isBeforeAdvice = false; - this.isAfterAdvice = false; - } - else { - switch (aspectJAnnotation.getAnnotationType()) { - case AtAfter: - case AtAfterReturning: - case AtAfterThrowing: - this.isAfterAdvice = true; - this.isBeforeAdvice = false; - break; - case AtAround: - case AtPointcut: - this.isAfterAdvice = false; - this.isBeforeAdvice = false; - break; - case AtBefore: - this.isAfterAdvice = false; - this.isBeforeAdvice = true; - } - } - } - - - @Override - public String toString() { - return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() + - "]; advice method [" + this.method + "]; perClauseKind=" + - this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind(); - - } - - - /** - * Pointcut implementation that changes its behaviour when the advice is instantiated. - * Note that this is a dynamic pointcut. Otherwise it might - * be optimized out if it does not at first match statically. - */ - private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut { - - private final AspectJExpressionPointcut declaredPointcut; - - private final Pointcut preInstantiationPointcut; - - private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory; - - private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut, - Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) { - this.declaredPointcut = declaredPointcut; - this.preInstantiationPointcut = preInstantiationPointcut; - if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) { - this.aspectInstanceFactory = (LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory; - } - } - - @Override - public boolean matches(Method method, Class targetClass) { - // We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut - return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) || - this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass); - } - - @Override - public boolean matches(Method method, Class targetClass, Object[] args) { - // This can match only on declared pointcut. - return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)); - } - - private boolean isAspectMaterialized() { - return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized()); - } - } - + implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation { + + private final AspectJExpressionPointcut declaredPointcut; + + private Pointcut pointcut; + + private final MetadataAwareAspectInstanceFactory aspectInstanceFactory; + + private final Method method; + + private final boolean lazy; + + private final AspectJAdvisorFactory atAspectJAdvisorFactory; + + private Advice instantiatedAdvice; + + private int declarationOrder; + + private String aspectName; + + private Boolean isBeforeAdvice; + + private Boolean isAfterAdvice; + + public InstantiationModelAwarePointcutAdvisorImpl( + AspectJAdvisorFactory af, + AspectJExpressionPointcut ajexp, + MetadataAwareAspectInstanceFactory aif, + Method method, + int declarationOrderInAspect, + String aspectName) { + + this.declaredPointcut = ajexp; + this.method = method; + this.atAspectJAdvisorFactory = af; + this.aspectInstanceFactory = aif; + this.declarationOrder = declarationOrderInAspect; + this.aspectName = aspectName; + + if (aif.getAspectMetadata().isLazilyInstantiated()) { + // Static part of the pointcut is a lazy type. + Pointcut preInstantiationPointcut = + Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); + + // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. + // If it's not a dynamic pointcut, it may be optimized out + // by the Spring AOP infrastructure after the first evaluation. + this.pointcut = + new PerTargetInstantiationModelPointcut( + this.declaredPointcut, preInstantiationPointcut, aif); + this.lazy = true; + } else { + // A singleton aspect. + this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); + this.pointcut = declaredPointcut; + this.lazy = false; + } + } + + /** + * The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change depending on + * the state of the advice. + */ + @Override + public Pointcut getPointcut() { + return this.pointcut; + } + + /** + * This is only of interest for Spring AOP: AspectJ instantiation semantics are much richer. In + * AspectJ terminology, all a return of {@code true} means here is that the aspect is not a + * SINGLETON. + */ + @Override + public boolean isPerInstance() { + return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON); + } + + /** Return the AspectJ AspectMetadata for this advisor. */ + public AspectMetadata getAspectMetadata() { + return this.aspectInstanceFactory.getAspectMetadata(); + } + + /** Lazily instantiate advice if necessary. */ + @Override + public synchronized Advice getAdvice() { + if (this.instantiatedAdvice == null) { + this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); + } + return this.instantiatedAdvice; + } + + @Override + public boolean isLazy() { + return this.lazy; + } + + @Override + public synchronized boolean isAdviceInstantiated() { + return (this.instantiatedAdvice != null); + } + + private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { + return this.atAspectJAdvisorFactory.getAdvice( + this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); + } + + public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() { + return this.aspectInstanceFactory; + } + + public AspectJExpressionPointcut getDeclaredPointcut() { + return this.declaredPointcut; + } + + @Override + public int getOrder() { + return this.aspectInstanceFactory.getOrder(); + } + + @Override + public String getAspectName() { + return this.aspectName; + } + + @Override + public int getDeclarationOrder() { + return this.declarationOrder; + } + + @Override + public boolean isBeforeAdvice() { + if (this.isBeforeAdvice == null) { + determineAdviceType(); + } + return this.isBeforeAdvice; + } + + @Override + public boolean isAfterAdvice() { + if (this.isAfterAdvice == null) { + determineAdviceType(); + } + return this.isAfterAdvice; + } + + /** + * Duplicates some logic from getAdvice, but importantly does not force creation of the advice. + */ + private void determineAdviceType() { + AbstractAspectJAdvisorFactory.AspectJAnnotation aspectJAnnotation = + AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method); + if (aspectJAnnotation == null) { + this.isBeforeAdvice = false; + this.isAfterAdvice = false; + } else { + switch (aspectJAnnotation.getAnnotationType()) { + case AtAfter: + case AtAfterReturning: + case AtAfterThrowing: + this.isAfterAdvice = true; + this.isBeforeAdvice = false; + break; + case AtAround: + case AtPointcut: + this.isAfterAdvice = false; + this.isBeforeAdvice = false; + break; + case AtBefore: + this.isAfterAdvice = false; + this.isBeforeAdvice = true; + } + } + } + + @Override + public String toString() { + return "InstantiationModelAwarePointcutAdvisor: expression [" + + getDeclaredPointcut().getExpression() + + "]; advice method [" + + this.method + + "]; perClauseKind=" + + this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind(); + } + + /** + * Pointcut implementation that changes its behaviour when the advice is instantiated. Note that + * this is a dynamic pointcut. Otherwise it might be optimized out if it does not at first + * match statically. + */ + private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut { + + private final AspectJExpressionPointcut declaredPointcut; + + private final Pointcut preInstantiationPointcut; + + private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory; + + private PerTargetInstantiationModelPointcut( + AspectJExpressionPointcut declaredPointcut, + Pointcut preInstantiationPointcut, + MetadataAwareAspectInstanceFactory aspectInstanceFactory) { + this.declaredPointcut = declaredPointcut; + this.preInstantiationPointcut = preInstantiationPointcut; + if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) { + this.aspectInstanceFactory = + (LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory; + } + } + + @Override + public boolean matches(Method method, Class targetClass) { + // We're either instantiated and matching on declared pointcut, or uninstantiated matching on + // either pointcut + return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) + || this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass); + } + + @Override + public boolean matches(Method method, Class targetClass, Object[] args) { + // This can match only on declared pointcut. + return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)); + } + + private boolean isAspectMaterialized() { + return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized()); + } + } } diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/LazySingletonAspectInstanceFactoryDecorator.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/LazySingletonAspectInstanceFactoryDecorator.java index 5d6c0b584..5a04eadee 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/LazySingletonAspectInstanceFactoryDecorator.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/LazySingletonAspectInstanceFactoryDecorator.java @@ -16,7 +16,6 @@ package com.fr.third.springframework.aop.aspectj; -import com.fr.third.aspectj.lang.annotation.AspectMetadata; import com.fr.third.springframework.util.Assert; /** diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/MetadataAwareAspectInstanceFactory.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/MetadataAwareAspectInstanceFactory.java index df862bb21..e8e3c107c 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/MetadataAwareAspectInstanceFactory.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/MetadataAwareAspectInstanceFactory.java @@ -16,10 +16,9 @@ package com.fr.third.springframework.aop.aspectj; -import com.fr.third.aspectj.lang.annotation.AspectMetadata; /** - * Subinterface of {@link com.fr.third.aspectj.AspectInstanceFactory} + * Subinterface of {@link com.fr.third.springframework.aop.aspectj.AspectInstanceFactory} * that returns {@link AspectMetadata} associated with AspectJ-annotated classes. * *

Ideally, AspectInstanceFactory would include this method itself, but because diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/SimpleMetadataAwareAspectInstanceFactory.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/SimpleMetadataAwareAspectInstanceFactory.java index f5f31424a..fd49ce1a9 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/SimpleMetadataAwareAspectInstanceFactory.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/SimpleMetadataAwareAspectInstanceFactory.java @@ -16,7 +16,6 @@ package com.fr.third.springframework.aop.aspectj; -import com.fr.third.aspectj.lang.annotation.AspectMetadata; import com.fr.third.springframework.core.Ordered; import com.fr.third.springframework.core.annotation.AnnotationUtils; import com.fr.third.springframework.core.annotation.Order; @@ -42,12 +41,12 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan */ public SimpleMetadataAwareAspectInstanceFactory(Class aspectClass, String aspectName) { super(aspectClass); - this.metadata = new com.fr.third.aspectj.lang.annotation.AspectMetadata(aspectClass, aspectName); + this.metadata = new AspectMetadata(aspectClass, aspectName); } @Override - public final com.fr.third.aspectj.lang.annotation.AspectMetadata getAspectMetadata() { + public final AspectMetadata getAspectMetadata() { return this.metadata; } diff --git a/fine-spring/src/com/fr/third/springframework/aop/aspectj/SingletonMetadataAwareAspectInstanceFactory.java b/fine-spring/src/com/fr/third/springframework/aop/aspectj/SingletonMetadataAwareAspectInstanceFactory.java index dd4826776..e476b9d75 100644 --- a/fine-spring/src/com/fr/third/springframework/aop/aspectj/SingletonMetadataAwareAspectInstanceFactory.java +++ b/fine-spring/src/com/fr/third/springframework/aop/aspectj/SingletonMetadataAwareAspectInstanceFactory.java @@ -16,7 +16,6 @@ package com.fr.third.springframework.aop.aspectj; -import com.fr.third.aspectj.lang.annotation.AspectMetadata; import com.fr.third.springframework.core.Ordered; import com.fr.third.springframework.core.annotation.AnnotationUtils; import com.fr.third.springframework.core.annotation.Order; diff --git a/fine-spring/src/com/fr/third/springframework/core/io/ContextResource.java b/fine-spring/src/com/fr/third/springframework/core/io/ContextResource.java index 5bb698276..dcbdf066e 100644 --- a/fine-spring/src/com/fr/third/springframework/core/io/ContextResource.java +++ b/fine-spring/src/com/fr/third/springframework/core/io/ContextResource.java @@ -19,7 +19,7 @@ package com.fr.third.springframework.core.io; /** * Extended interface for a resource that is loaded from an enclosing * 'context', e.g. from a {@link javax.servlet.ServletContext} or a - * {@link javax.portlet.PortletContext} but also from plain classpath paths + * {@link com.fr.third.javax.portlet.PortletContext} but also from plain classpath paths * or relative file system paths (specified without an explicit prefix, * hence applying relative to the local {@link ResourceLoader}'s context). * diff --git a/fine-spring/src/com/fr/third/springframework/web/bind/annotation/ExceptionHandler.java b/fine-spring/src/com/fr/third/springframework/web/bind/annotation/ExceptionHandler.java index 9626ab443..3582c8216 100644 --- a/fine-spring/src/com/fr/third/springframework/web/bind/annotation/ExceptionHandler.java +++ b/fine-spring/src/com/fr/third/springframework/web/bind/annotation/ExceptionHandler.java @@ -37,13 +37,13 @@ import java.lang.annotation.Target; *

  • Request and/or response objects (Servlet API or Portlet API). * You may choose any specific request/response type, e.g. * {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest} - * or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} / - * {@link javax.portlet.RenderRequest}. Note that in the Portlet case, + * or {@link com.fr.third.javax.portlet.PortletRequest} / {@link com.fr.third.javax.portlet.ActionRequest} / + * {@link com.fr.third.javax.portlet.RenderRequest}. Note that in the Portlet case, * an explicitly declared action/render argument is also used for mapping * specific request types onto a handler method (in case of no other * information given that differentiates between action and render requests). *
  • Session object (Servlet API or Portlet API): either - * {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}. + * {@link javax.servlet.http.HttpSession} or {@link com.fr.third.javax.portlet.PortletSession}. * An argument of this type will enforce the presence of a corresponding session. * As a consequence, such an argument will never be {@code null}. * Note that session access may not be thread-safe, in particular in a @@ -88,7 +88,7 @@ import java.lang.annotation.Target; *
  • {@code void} if the method handles the response itself (by * writing the response content directly, declaring an argument of type * {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse} - * / {@link javax.portlet.RenderResponse} for that purpose) + * / {@link com.fr.third.javax.portlet.RenderResponse} for that purpose) * or if the view name is supposed to be implicitly determined through a * {@link com.fr.third.springframework.web.servlet.RequestToViewNameTranslator} * (not declaring a response argument in the handler method signature; diff --git a/fine-spring/src/com/fr/third/springframework/web/bind/annotation/RequestMapping.java b/fine-spring/src/com/fr/third/springframework/web/bind/annotation/RequestMapping.java index c1d1f7263..66468aea0 100644 --- a/fine-spring/src/com/fr/third/springframework/web/bind/annotation/RequestMapping.java +++ b/fine-spring/src/com/fr/third/springframework/web/bind/annotation/RequestMapping.java @@ -46,13 +46,13 @@ import java.util.concurrent.Callable; *
  • Request and/or response objects (Servlet API or Portlet API). * You may choose any specific request/response type, e.g. * {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest} - * or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} / - * {@link javax.portlet.RenderRequest}. Note that in the Portlet case, + * or {@link com.fr.third.javax.portlet.PortletRequest} / {@link com.fr.third.javax.portlet.ActionRequest} / + * {@link com.fr.third.javax.portlet.RenderRequest}. Note that in the Portlet case, * an explicitly declared action/render argument is also used for mapping * specific request types onto a handler method (in case of no other * information given that differentiates between action and render requests). *
  • Session object (Servlet API or Portlet API): either - * {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}. + * {@link javax.servlet.http.HttpSession} or {@link com.fr.third.javax.portlet.PortletSession}. * An argument of this type will enforce the presence of a corresponding session. * As a consequence, such an argument will never be {@code null}. * Note that session access may not be thread-safe, in particular in a @@ -207,7 +207,7 @@ import java.util.concurrent.Callable; *
  • {@code void} if the method handles the response itself (by * writing the response content directly, declaring an argument of type * {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse} - * / {@link javax.portlet.RenderResponse} for that purpose) + * / {@link com.fr.third.javax.portlet.RenderResponse} for that purpose) * or if the view name is supposed to be implicitly determined through a * {@link com.fr.third.springframework.web.servlet.RequestToViewNameTranslator} * (not declaring a response argument in the handler method signature; diff --git a/fine-spring/src/com/fr/third/springframework/web/context/request/FacesRequestAttributes.java b/fine-spring/src/com/fr/third/springframework/web/context/request/FacesRequestAttributes.java index c210c0fec..736803405 100644 --- a/fine-spring/src/com/fr/third/springframework/web/context/request/FacesRequestAttributes.java +++ b/fine-spring/src/com/fr/third/springframework/web/context/request/FacesRequestAttributes.java @@ -20,7 +20,7 @@ import java.lang.reflect.Method; import java.util.Map; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; -import javax.portlet.PortletSession; +import com.fr.third.javax.portlet.PortletSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/fine-spring/src/com/fr/third/springframework/web/context/request/NativeWebRequest.java b/fine-spring/src/com/fr/third/springframework/web/context/request/NativeWebRequest.java index 6d37b11c0..28cc7551d 100644 --- a/fine-spring/src/com/fr/third/springframework/web/context/request/NativeWebRequest.java +++ b/fine-spring/src/com/fr/third/springframework/web/context/request/NativeWebRequest.java @@ -31,16 +31,16 @@ public interface NativeWebRequest extends WebRequest { /** * Return the underlying native request object, if available. * @see javax.servlet.http.HttpServletRequest - * @see javax.portlet.ActionRequest - * @see javax.portlet.RenderRequest + * @see com.fr.third.javax.portlet.ActionRequest + * @see com.fr.third.javax.portlet.RenderRequest */ Object getNativeRequest(); /** * Return the underlying native response object, if available. * @see javax.servlet.http.HttpServletResponse - * @see javax.portlet.ActionResponse - * @see javax.portlet.RenderResponse + * @see com.fr.third.javax.portlet.ActionResponse + * @see com.fr.third.javax.portlet.RenderResponse */ Object getNativeResponse(); @@ -50,8 +50,8 @@ public interface NativeWebRequest extends WebRequest { * @return the matching request object, or {@code null} if none * of that type is available * @see javax.servlet.http.HttpServletRequest - * @see javax.portlet.ActionRequest - * @see javax.portlet.RenderRequest + * @see com.fr.third.javax.portlet.ActionRequest + * @see com.fr.third.javax.portlet.RenderRequest */ T getNativeRequest(Class requiredType); @@ -61,8 +61,8 @@ public interface NativeWebRequest extends WebRequest { * @return the matching response object, or {@code null} if none * of that type is available * @see javax.servlet.http.HttpServletResponse - * @see javax.portlet.ActionResponse - * @see javax.portlet.RenderResponse + * @see com.fr.third.javax.portlet.ActionResponse + * @see com.fr.third.javax.portlet.RenderResponse */ T getNativeResponse(Class requiredType); diff --git a/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsFileUploadSupport.java b/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsFileUploadSupport.java index 7a4e63f6c..e7b488f7d 100644 --- a/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsFileUploadSupport.java +++ b/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsFileUploadSupport.java @@ -23,10 +23,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.FileUpload; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import com.fr.third.org.apache.commons.fileupload.FileItem; +import com.fr.third.org.apache.commons.fileupload.FileItemFactory; +import com.fr.third.org.apache.commons.fileupload.FileUpload; +import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -82,7 +82,7 @@ public abstract class CommonsFileUploadSupport { /** - * Return the underlying {@code org.apache.commons.fileupload.disk.DiskFileItemFactory} + * Return the underlying {@code com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory} * instance. There is hardly any need to access this. * @return the underlying DiskFileItemFactory instance */ @@ -91,7 +91,7 @@ public abstract class CommonsFileUploadSupport { } /** - * Return the underlying {@code org.apache.commons.fileupload.FileUpload} + * Return the underlying {@code com.fr.third.org.apache.commons.fileupload.FileUpload} * instance. There is hardly any need to access this. * @return the underlying FileUpload instance */ @@ -103,7 +103,7 @@ public abstract class CommonsFileUploadSupport { * Set the maximum allowed size (in bytes) before uploads are refused. * -1 indicates no limit (the default). * @param maxUploadSize the maximum upload size allowed - * @see org.apache.commons.fileupload.FileUploadBase#setSizeMax + * @see com.fr.third.org.apache.commons.fileupload.FileUploadBase#setSizeMax */ public void setMaxUploadSize(long maxUploadSize) { this.fileUpload.setSizeMax(maxUploadSize); @@ -114,7 +114,7 @@ public abstract class CommonsFileUploadSupport { * Uploaded files will still be received past this amount, but they will not be * stored in memory. Default is 10240, according to Commons FileUpload. * @param maxInMemorySize the maximum in memory size allowed - * @see org.apache.commons.fileupload.disk.DiskFileItemFactory#setSizeThreshold + * @see com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory#setSizeThreshold */ public void setMaxInMemorySize(int maxInMemorySize) { this.fileItemFactory.setSizeThreshold(maxInMemorySize); @@ -132,7 +132,7 @@ public abstract class CommonsFileUploadSupport { * @see javax.servlet.ServletRequest#getCharacterEncoding * @see javax.servlet.ServletRequest#setCharacterEncoding * @see WebUtils#DEFAULT_CHARACTER_ENCODING - * @see org.apache.commons.fileupload.FileUploadBase#setHeaderEncoding + * @see com.fr.third.org.apache.commons.fileupload.FileUploadBase#setHeaderEncoding */ public void setDefaultEncoding(String defaultEncoding) { this.fileUpload.setHeaderEncoding(defaultEncoding); @@ -270,7 +270,7 @@ public abstract class CommonsFileUploadSupport { * potentially holding temporary data on disk. *

    Deletes the underlying Commons FileItem instances. * @param multipartFiles Collection of MultipartFile instances - * @see org.apache.commons.fileupload.FileItem#delete() + * @see com.fr.third.org.apache.commons.fileupload.FileItem#delete() */ protected void cleanupFileItems(MultiValueMap multipartFiles) { for (List files : multipartFiles.values()) { diff --git a/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartFile.java b/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartFile.java index 7e37c2255..5d1b510fe 100644 --- a/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartFile.java +++ b/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartFile.java @@ -21,9 +21,9 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItem; +import com.fr.third.org.apache.commons.fileupload.FileItem; +import com.fr.third.org.apache.commons.fileupload.FileUploadException; +import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItem; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -57,7 +57,7 @@ public class CommonsMultipartFile implements MultipartFile, Serializable { } /** - * Return the underlying {@code org.apache.commons.fileupload.FileItem} + * Return the underlying {@code com.fr.third.org.apache.commons.fileupload.FileItem} * instance. There is hardly any need to access this. */ public final FileItem getFileItem() { diff --git a/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartResolver.java b/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartResolver.java index 441738965..27cc38a58 100644 --- a/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartResolver.java +++ b/fine-spring/src/com/fr/third/springframework/web/multipart/commons/CommonsMultipartResolver.java @@ -20,12 +20,12 @@ import java.util.List; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.FileUpload; -import org.apache.commons.fileupload.FileUploadBase; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.servlet.ServletFileUpload; +import com.fr.third.org.apache.commons.fileupload.FileItem; +import com.fr.third.org.apache.commons.fileupload.FileItemFactory; +import com.fr.third.org.apache.commons.fileupload.FileUpload; +import com.fr.third.org.apache.commons.fileupload.FileUploadBase; +import com.fr.third.org.apache.commons.fileupload.FileUploadException; +import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload; import com.fr.third.springframework.util.Assert; import com.fr.third.springframework.web.context.ServletContextAware; @@ -56,8 +56,8 @@ import com.fr.third.springframework.web.util.WebUtils; * @see #CommonsMultipartResolver(ServletContext) * @see #setResolveLazily * @see com.fr.third.springframework.web.portlet.multipart.CommonsPortletMultipartResolver - * @see org.apache.commons.fileupload.servlet.ServletFileUpload - * @see org.apache.commons.fileupload.disk.DiskFileItemFactory + * @see com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload + * @see com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory */ public class CommonsMultipartResolver extends CommonsFileUploadSupport implements MultipartResolver, ServletContextAware { @@ -101,7 +101,7 @@ public class CommonsMultipartResolver extends CommonsFileUploadSupport } /** - * Initialize the underlying {@code org.apache.commons.fileupload.servlet.ServletFileUpload} + * Initialize the underlying {@code com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload} * instance. Can be overridden to use a custom subclass, e.g. for testing purposes. * @param fileItemFactory the Commons FileItemFactory to use * @return the new ServletFileUpload instance From 8399a7ce943508215ba21de59880451300b5c55b Mon Sep 17 00:00:00 2001 From: hzzz Date: Tue, 5 Jun 2018 23:24:14 +0800 Subject: [PATCH 2/2] fix --- fine-portlet-api/.DS_Store | Bin 0 -> 6148 bytes fine-portlet-api/src/.DS_Store | Bin 0 -> 6148 bytes fine-portlet-api/src/com/.DS_Store | Bin 0 -> 6148 bytes fine-portlet-api/src/com/fr/third/.DS_Store | Bin 0 -> 6148 bytes .../fr/third/javax/portlet/ActionRequest.java | 162 +++++ .../third/javax/portlet/ActionResponse.java | 225 ++++++ .../third/javax/portlet/GenericPortlet.java | 464 ++++++++++++ .../fr/third/javax/portlet/PortalContext.java | 108 +++ .../com/fr/third/javax/portlet/Portlet.java | 183 +++++ .../fr/third/javax/portlet/PortletConfig.java | 118 +++ .../third/javax/portlet/PortletContext.java | 456 ++++++++++++ .../third/javax/portlet/PortletException.java | 160 +++++ .../fr/third/javax/portlet/PortletMode.java | 154 ++++ .../javax/portlet/PortletModeException.java | 107 +++ .../javax/portlet/PortletPreferences.java | 265 +++++++ .../third/javax/portlet/PortletRequest.java | 669 ++++++++++++++++++ .../portlet/PortletRequestDispatcher.java | 80 +++ .../third/javax/portlet/PortletResponse.java | 113 +++ .../portlet/PortletSecurityException.java | 89 +++ .../third/javax/portlet/PortletSession.java | 377 ++++++++++ .../javax/portlet/PortletSessionUtil.java | 90 +++ .../fr/third/javax/portlet/PortletURL.java | 211 ++++++ .../javax/portlet/PreferencesValidator.java | 53 ++ .../javax/portlet/ReadOnlyException.java | 88 +++ .../fr/third/javax/portlet/RenderRequest.java | 43 ++ .../third/javax/portlet/RenderResponse.java | 342 +++++++++ .../javax/portlet/UnavailableException.java | 134 ++++ .../javax/portlet/ValidatorException.java | 132 ++++ .../fr/third/javax/portlet/WindowState.java | 135 ++++ .../javax/portlet/WindowStateException.java | 105 +++ .../fr/third/javax/portlet/package-info.java | 38 + 31 files changed, 5101 insertions(+) create mode 100644 fine-portlet-api/.DS_Store create mode 100644 fine-portlet-api/src/.DS_Store create mode 100644 fine-portlet-api/src/com/.DS_Store create mode 100644 fine-portlet-api/src/com/fr/third/.DS_Store create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/ActionRequest.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/ActionResponse.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/GenericPortlet.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortalContext.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/Portlet.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletConfig.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletContext.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletException.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletMode.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletModeException.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletPreferences.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequest.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequestDispatcher.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletResponse.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletSecurityException.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletSession.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletSessionUtil.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PortletURL.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/PreferencesValidator.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/ReadOnlyException.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/RenderRequest.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/RenderResponse.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/UnavailableException.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/ValidatorException.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/WindowState.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/WindowStateException.java create mode 100755 fine-portlet-api/src/com/fr/third/javax/portlet/package-info.java diff --git a/fine-portlet-api/.DS_Store b/fine-portlet-api/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0S5Z-O8ZYyFAf<5Nqt%v@IJqaP!gEt|f2bDG<)dp%(n$(~*lGo5T@(Fw$ zXLdJYvEWU_&cN;0j;iayU4o2iShc}Kq(BHht zIMBYo4*2aQcEhG#8c)7{f1EU%@4Qs5tgUYdQ4_VT+O;!^QYUefS!}!0OSDeiWaMf6 zEQ-dTy6c?>!?bVg97SQ`2H|ijlLLPUAy*ec=trp?%|btx^Ek>OL{(J#MtweSwVMsI z({5)CbKdQOzTY{>vZ~nKYaN~p?j9cJPucT}VwVH?Qnob~@Cu47?%tV(<0!lZyNE4f z2#En=fEXYKR*nIE6o}20tDFiZ28e;57{L9(gobEo%oWP513J7uqrZZP0y@4W5KWDi z##|wIK)6Z;RH9xq(34&$Z_XWUXqJuyHGEHY45 zrh(`GG5j)1ANh+ZWDx_zz&~SvS9(s*hNAS@`mH=XYfWeaXebz$qXGi@!X*F<+(+ut esr)AD5NB!372+&7F4F<&A|MH&ju`j_20j2Ft4`ej literal 0 HcmV?d00001 diff --git a/fine-portlet-api/src/com/fr/third/.DS_Store b/fine-portlet-api/src/com/fr/third/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f9508f2a4cec5dd5bcc934705228f05a56aaced0 GIT binary patch literal 6148 zcmeHKI|>3Z5S{S@f{mqRuHX%V=n3`$3W6Y_ASjkwc`lFUn@^!Ec3LQJVDgg5yo9`B zXGcVIe%{PPCL%I|8_LawuGzkM$9fr2ARK30FU{$&KOVN7+;;)v4rM26xxk6^$E}G4U=FOTNiu&z1zj(T64dh4#sKBcN{a8+{{x9Kg z`u|rFS5$xs{FMSaSTu_{o|Lt<^Ej)u1-^n?&K+)sxl=HBIR<(;#=^?+)RQ8w*c|&c Vu?=)O;!X$hXTWr!QGstO@Bm;x6xaX& literal 0 HcmV?d00001 diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/ActionRequest.java b/fine-portlet-api/src/com/fr/third/javax/portlet/ActionRequest.java new file mode 100755 index 000000000..2cdb35e5c --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/ActionRequest.java @@ -0,0 +1,162 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The ActionRequest represents the request sent to the portlet + * to handle an action. + * It extends the PortletRequest interface to provide action request + * information to portlets.
    + * The portlet container creates an ActionRequest object and + * passes it as argument to the portlet's processAction method. + * + * @see PortletRequest + * @see RenderRequest + */ +public interface ActionRequest extends PortletRequest +{ + + + + /** + * Retrieves the body of the HTTP request from client to + * portal as binary data using + * an InputStream. Either this method or + * {@link #getReader} may be called to read the body, but not both. + *

    + * For HTTP POST data of type application/x-www-form-urlencoded + * this method throws an IllegalStateException + * as this data has been already processed by the + * portal/portlet-container and is available as request parameters. + * + * @return an input stream containing the body of the request + * + * @exception java.lang.IllegalStateException + * if getReader was already called, or it is a + * HTTP POST data of type application/x-www-form-urlencoded + * @exception java.io.IOException + * if an input or output exception occurred + */ + public java.io.InputStream getPortletInputStream () throws java.io.IOException; + + + + /** + * Overrides the name of the character encoding used in the body of this + * request. This method must be called prior to reading input + * using {@link #getReader} or {@link #getPortletInputStream}. + *

    + * This method only sets the character set for the Reader that the + * {@link #getReader} method returns. + * + * @param enc a String containing the name of + * the chararacter encoding. + * + * @exception java.io.UnsupportedEncodingException if this is not a valid encoding + * @exception java.lang.IllegalStateException if this method is called after + * reading request parameters or reading input using + * getReader() + */ + + public void setCharacterEncoding(String enc) + throws java.io.UnsupportedEncodingException; + + + /** + * Retrieves the body of the HTTP request from the client to the portal + * as character data using + * a BufferedReader. The reader translates the character + * data according to the character encoding used on the body. + * Either this method or {@link #getPortletInputStream} may be called to read the + * body, not both. + *

    + * For HTTP POST data of type application/x-www-form-urlencoded + * this method throws an IllegalStateException + * as this data has been already processed by the + * portal/portlet-container and is available as request parameters. + * + * @return a BufferedReader + * containing the body of the request + * + * @exception java.io.UnsupportedEncodingException + * if the character set encoding used is + * not supported and the text cannot be decoded + * @exception java.lang.IllegalStateException + * if {@link #getPortletInputStream} method + * has been called on this request, it is a + * HTTP POST data of type application/x-www-form-urlencoded. + * @exception java.io.IOException + * if an input or output exception occurred + * + * @see #getPortletInputStream + */ + + public java.io.BufferedReader getReader() + throws java.io.UnsupportedEncodingException, java.io.IOException; + + + /** + * Returns the name of the character encoding used in the body of this request. + * This method returns null if the request + * does not specify a character encoding. + * + * @return a String containing the name of + * the chararacter encoding, or null + * if the request does not specify a character encoding. + */ + + public java.lang.String getCharacterEncoding(); + + + + /** + * Returns the MIME type of the body of the request, + * or null if the type is not known. + * + * @return a String containing the name + * of the MIME type of the request, or null + * if the type is not known. + */ + + public java.lang.String getContentType(); + + + /** + * Returns the length, in bytes, of the request body + * which is made available by the input stream, or -1 if the + * length is not known. + * + * + * @return an integer containing the length of the + * request body or -1 if the length is not known + * + */ + + public int getContentLength(); + + + + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/ActionResponse.java b/fine-portlet-api/src/com/fr/third/javax/portlet/ActionResponse.java new file mode 100755 index 000000000..1e83abd57 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/ActionResponse.java @@ -0,0 +1,225 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The ActionResponse interface represents the portlet + * response to an action request. + * It extends the PortletResponse interface to provide specific + * action response functionality to portlets.
    + * The portlet container creates an ActionResponse object and + * passes it as argument to the portlet's processAction method. + * + * @see ActionRequest + * @see PortletResponse + */ +public interface ActionResponse extends PortletResponse +{ + + + /** + * Sets the window state of a portlet to the given window state. + *

    + * Possible values are the standard window states and any custom + * window states supported by the portal and the portlet. + * Standard window states are: + *

      + *
    • MINIMIZED + *
    • NORMAL + *
    • MAXIMIZED + *
    + * + * @param windowState + * the new portlet window state + * + * @exception WindowStateException + * if the portlet cannot switch to the specified window state. + * To avoid this exception the portlet can check the allowed + * window states with Request.isWindowStateAllowed(). + * @exception java.lang.IllegalStateException + * if the method is invoked after sendRedirect has been called. + * + * @see WindowState + */ + + public void setWindowState (WindowState windowState) + throws WindowStateException; + + + /** + * Sets the portlet mode of a portlet to the given portlet mode. + *

    + * Possible values are the standard portlet modes and any custom + * portlet modes supported by the portal and the portlet. Portlets + * must declare in the deployment descriptor the portlet modes they + * support for each markup type. + * Standard portlet modes are: + *

      + *
    • EDIT + *
    • HELP + *
    • VIEW + *
    + *

    + * Note: The portlet may still be called in a different window + * state in the next render call, depending on the portlet container / portal. + * + * @param portletMode + * the new portlet mode + * + * @exception PortletModeException + * if the portlet cannot switch to this portlet mode, + * because the portlet or portal does not support it for this markup, + * or the current user is not allowed to switch to this portlet mode. + * To avoid this exception the portlet can check the allowed + * portlet modes with Request.isPortletModeAllowed(). + * @exception java.lang.IllegalStateException + * if the method is invoked after sendRedirect has been called. + */ + + public void setPortletMode (PortletMode portletMode) + throws PortletModeException; + + + /** + * Instructs the portlet container to send a redirect response + * to the client using the specified redirect location URL. + *

    + * This method only accepts an absolute URL (e.g. + * http://my.co/myportal/mywebap/myfolder/myresource.gif) + * or a full path URI (e.g. /myportal/mywebap/myfolder/myresource.gif). + * If required, + * the portlet container may encode the given URL before the + * redirection is issued to the client. + *

    + * The sendRedirect method can not be invoked after any of the + * following methods of the ActionResponse interface has been called: + *

      + *
    • setPortletMode + *
    • setWindowState + *
    • setRenderParameter + *
    • setRenderParameters + *
    + * + * @param location the redirect location URL + * + * @exception java.io.IOException + * if an input or output exception occurs. + * @exception java.lang.IllegalArgumentException + * if a relative path URL is given + * @exception java.lang.IllegalStateException + * if the method is invoked after any of above mentioned methods of + * the ActionResponse interface has been called. + */ + + public void sendRedirect(String location) + throws java.io.IOException; + + + /** + * Sets a parameter map for the render request. + *

    + * All previously set render parameters are cleared. + *

    + * These parameters will be accessible in all + * sub-sequent render calls via the + * PortletRequest.getParameter call until + * a new request is targeted to the portlet. + *

    + * The given parameters do not need to be encoded + * prior to calling this method. + * + * @param parameters Map containing parameter names for + * the render phase as + * keys and parameter values as map + * values. The keys in the parameter + * map must be of type String. The values + * in the parameter map must be of type + * String array (String[]). + * + * @exception java.lang.IllegalArgumentException + * if parameters is null, if + * any of the key/values in the Map are null, + * if any of the keys is not a String, or if any of + * the values is not a String array. + * @exception java.lang.IllegalStateException + * if the method is invoked after sendRedirect has been called. + */ + + public void setRenderParameters(java.util.Map parameters); + + + /** + * Sets a String parameter for the render request. + *

    + * These parameters will be accessible in all + * sub-sequent render calls via the + * PortletRequest.getParameter call until + * a request is targeted to the portlet. + *

    + * This method replaces all parameters with the given key. + *

    + * The given parameter do not need to be encoded + * prior to calling this method. + * + * @param key key of the render parameter + * @param value value of the render parameter + * + * @exception java.lang.IllegalArgumentException + * if key or value are null. + * @exception java.lang.IllegalStateException + * if the method is invoked after sendRedirect has been called. + */ + + public void setRenderParameter(String key, String value); + + + /** + * Sets a String array parameter for the render request. + *

    + * These parameters will be accessible in all + * sub-sequent render calls via the + * PortletRequest.getParameter call until + * a request is targeted to the portlet. + *

    + * This method replaces all parameters with the given key. + *

    + * The given parameter do not need to be encoded + * prior to calling this method. + * + * @param key key of the render parameter + * @param values values of the render parameter + * + * @exception java.lang.IllegalArgumentException + * if key or value are null. + * @exception java.lang.IllegalStateException + * if the method is invoked after sendRedirect has been called. + */ + + public void setRenderParameter(String key, String[] values); + + +} + + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/GenericPortlet.java b/fine-portlet-api/src/com/fr/third/javax/portlet/GenericPortlet.java new file mode 100755 index 000000000..1a4c9f15e --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/GenericPortlet.java @@ -0,0 +1,464 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + +/** + * The GenericPortlet class provides a default implementation + * for the Portlet interface. + *

    + * It provides an abstract class to be subclassed to create portlets. A + * subclass of GenericPortlet should override at least + * one method, usually one of the following: + *

      + *
    • processAction, to handle action requests
    • + *
    • doView, to handle render requests when in VIEW mode
    • + *
    • doEdit, to handle render requests when in EDIT mode
    • + *
    • doHelp, to handle render request when in HELP mode
    • + *
    • init and destroy, to manage resources that are held for the life of + * the servlet
    • + *
    + *

    + * Normally there is no need to override the render or the doDispatch + * methods. Render handles render requests setting the title of the + * portlet in the response and invoking doDispatch. doDispatch dispatches + * the request to one of the doView, doEdit or doHelp method depending on + * the portlet mode indicated in the request. + *

    + * Portlets typically run on multithreaded servers, so please note that a + * portlet must handle concurrent requests and be careful to synchronize + * access to shared resources. Shared resources include in-memory data + * such as instance or class variables and external objects such as + * files, database connections, and network connections. + */ +public abstract class GenericPortlet implements Portlet, PortletConfig +{ + + + private transient PortletConfig config; + + /** + * Does nothing. + */ + + public GenericPortlet() + { + } + + + /** + * Called by the portlet container to indicate to a portlet that the + * portlet is being placed into service. + *

    + * The default implementation just stores the PortletConfig + * object. + *

    The portlet container calls the init + * method exactly once after instantiating the portlet. + * The init method must complete successfully + * before the portlet can receive any requests. + * + *

    The portlet container cannot place the portlet into service + * if the init method does one of the following: + *

      + *
    1. it throws a PortletException + *
    2. it does not return within a time period defined by the Web server + *
    + * + * + * @param config a PortletConfig object + * containing the portlet + * configuration and initialization parameters + * + * @exception PortletException if an exception has occurred that + * interferes with the portlet normal + * operation. + * @exception UnavailableException if the portlet cannot perform the initialization at this time. + */ + + public void init (PortletConfig config) throws PortletException + { + this.config = config; + this.init(); + } + + + /** + * + * A convenience method which can be overridden so that there's no need + * to call super.init(config). + * + *

    Instead of overriding {@link #init(PortletConfig)}, simply override + * this method and it will be called by + * GenericPortlet.init(PortletConfig config). + * The PortletConfig object can still be retrieved via {@link + * #getPortletConfig}. + * + * @exception PortletException if an exception has occurred that + * interferes with the portlet normal + * operation. + * @exception UnavailableException if the portlet is unavailable to perform init + */ + + public void init() throws PortletException + { + } + + + /** + * Called by the portlet container to allow the portlet to process + * an action request. This method is called if the client request was + * originated by a URL created (by the portlet) with the + * RenderResponse.createActionURL() method. + *

    + * The default implementation throws an exception. + * + * @param request + * the action request + * @param response + * the action response + * @exception PortletException + * if the portlet cannot fulfilling the request + * @exception UnavailableException + * if the portlet is unavailable to process the action at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception java.io.IOException + * if the streaming causes an I/O problem + */ + public void processAction (ActionRequest request, ActionResponse response) + throws PortletException, java.io.IOException { + throw new PortletException("processAction method not implemented"); + } + + + /** + * The default implementation of this method sets the title + * using the getTitle method and invokes the + * doDispatch method. + * + * @param request + * the render request + * @param response + * the render response + * + * @exception PortletException + * if the portlet cannot fulfilling the request + * @exception UnavailableException + * if the portlet is unavailable to perform render at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception java.io.IOException + * if the streaming causes an I/O problem + * + */ + public void render (RenderRequest request, + RenderResponse response) + throws PortletException, java.io.IOException + { + response.setTitle(getTitle(request)); + doDispatch(request, response); + } + + + + /** + * Used by the render method to get the title. + *

    + * The default implementation gets the title from the ResourceBundle + * of the PortletConfig of the portlet. The title is retrieved + * using the 'javax.portlet.title' resource name. + *

    + * Portlets can overwrite this method to provide dynamic + * titles (e.g. based on locale, client, and session information). + * Examples are: + *

      + *
    • language-dependant titles for multi-lingual portals + *
    • shorter titles for WAP phones + *
    • the number of messages in a mailbox portlet + *
    + * + * @return the portlet title for this window + */ + + protected java.lang.String getTitle(RenderRequest request) { + return config.getResourceBundle(request.getLocale()).getString("javax.portlet.title"); + } + + + /** + * The default implementation of this method routes the render request + * to a set of helper methods depending on the current portlet mode the + * portlet is currently in. + * These methods are: + *
      + *
    • doView for handling view requests + *
    • doEdit for handling edit requests + *
    • doHelp for handling help requests + *
    + *

    + * If the window state of this portlet is minimized, this + * method does not invoke any of the portlet mode rendering methods. + *

    + * For handling custom portlet modes the portlet should override this + * method. + * + * @param request + * the render request + * @param response + * the render response + * + * @exception PortletException + * if the portlet cannot fulfilling the request + * @exception UnavailableException + * if the portlet is unavailable to perform render at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception java.io.IOException + * if the streaming causes an I/O problem + * + * @see #doView(RenderRequest, RenderResponse) + * @see #doEdit(RenderRequest, RenderResponse) + * @see #doHelp(RenderRequest, RenderResponse) + */ + protected void doDispatch (RenderRequest request, + RenderResponse response) throws PortletException,java.io.IOException + { + WindowState state = request.getWindowState(); + + if ( ! state.equals(WindowState.MINIMIZED)) { + PortletMode mode = request.getPortletMode(); + if (mode.equals(PortletMode.VIEW)) { + doView (request, response); + } + else if (mode.equals(PortletMode.EDIT)) { + doEdit (request, response); + } + else if (mode.equals(PortletMode.HELP)) { + doHelp (request, response); + } + else { + throw new PortletException("unknown portlet mode: " + mode); + } + } + + } + + + /** + * Helper method to serve up the mandatory view mode. + *

    + * The default implementation throws an exception. + * + * @param request + * the portlet request + * @param response + * the render response + * + * @exception PortletException + * if the portlet cannot fulfilling the request + * @exception UnavailableException + * if the portlet is unavailable to perform render at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception java.io.IOException + * if the streaming causes an I/O problem + * + */ + + protected void doView (RenderRequest request, + RenderResponse response) + throws PortletException, java.io.IOException + { + throw new PortletException("doView method not implemented"); + } + + + /** + * Helper method to serve up the edit mode. + *

    + * The default implementation throws an exception. + * + * @param request + * the portlet request + * @param response + * the render response + * + * @exception PortletException + * if the portlet cannot fulfilling the request + * @exception UnavailableException + * if the portlet is unavailable to perform render at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception java.io.IOException + * if the streaming causes an I/O problem + * + */ + + protected void doEdit (RenderRequest request, + RenderResponse response) + throws PortletException, java.io.IOException + { + throw new PortletException("doEdit method not implemented"); + } + + /** + * Helper method to serve up the help mode. + *

    + * The default implementation throws an exception. + * + * @param request + * the portlet request + * @param response + * the render response + * + * @exception PortletException + * if the portlet cannot fulfilling the request + * @exception UnavailableException + * if the portlet is unavailable to perform render at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception java.io.IOException + * if the streaming causes an I/O problem + */ + + protected void doHelp (RenderRequest request, + RenderResponse response) + throws PortletException, java.io.IOException + { + throw new PortletException("doHelp method not implemented"); + + } + + + + /** + * Returns the PortletConfig object of this portlet. + * + * @return the PortletConfig object of this portlet + */ + + public PortletConfig getPortletConfig () + { + return config; + } + + + /** + * Called by the portlet container to indicate to a portlet that the portlet + * is being taken out of service. + *

    + * The default implementation does nothing. + * + */ + + public void destroy () + { + // do nothing + } + + //------------------------------------------------------------------------- + // implement PortletConfig + //------------------------------------------------------------------------- + + + /** + * Returns the name of this portlet. + * + * @return the portlet name + * + * @see PortletConfig#getPortletName() + */ + + public String getPortletName () + { + return config.getPortletName(); + } + + + /** + * Returns the PortletContext of the portlet application + * the portlet is in. + * + * @return the portlet application context + */ + + public PortletContext getPortletContext () + { + return config.getPortletContext(); + } + + + + /** + * Gets the resource bundle for the given locale based on the + * resource bundle defined in the deployment descriptor + * with resource-bundle tag or the inlined resources + * defined in the deployment descriptor. + * + * @return the resource bundle for the given locale + */ + + public java.util.ResourceBundle getResourceBundle(java.util.Locale locale) + { + return config.getResourceBundle(locale); + } + + + /** + * Returns a String containing the value of the named initialization parameter, + * or null if the parameter does not exist. + * + * @param name a String specifying the name + * of the initialization parameter + * + * @return a String containing the value + * of the initialization parameter + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public String getInitParameter(java.lang.String name) + { + return config.getInitParameter(name); + } + + + /** + * Returns the names of the portlet initialization parameters as an + * Enumeration of String objects, or an empty Enumeration if the + * portlet has no initialization parameters. + * + * @return an Enumeration of String + * objects containing the names of the portlet + * initialization parameters, or an empty Enumeration if the + * portlet has no initialization parameters. + */ + + public java.util.Enumeration getInitParameterNames() + { + return config.getInitParameterNames(); + } +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortalContext.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortalContext.java new file mode 100755 index 000000000..525e8c234 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortalContext.java @@ -0,0 +1,108 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + +/** + * The PortalContext interface gives the portlet + * the ability to retrieve information about the portal calling this portlet. + *

    + * The portlet can only read the PortalContext data. + */ +public interface PortalContext +{ + + + + /** + * Returns the portal property with the given name, + * or a null if there is + * no property by that name. + * + * @param name property name + * + * @return portal property with key name + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public java.lang.String getProperty(java.lang.String name); + + + /** + * Returns all portal property names, or an empty + * Enumeration if there are no property names. + * + * @return All portal property names as an + * Enumeration of String objects + */ + public java.util.Enumeration getPropertyNames(); + + + /** + * Returns all supported portlet modes by the portal + * as an enumertation of PorltetMode objects. + *

    + * The portlet modes must at least include the + * standard portlet modes EDIT, HELP, VIEW. + * + * @return All supported portal modes by the portal + * as an enumertation of PorltetMode objects. + */ + + public java.util.Enumeration getSupportedPortletModes(); + + + /** + * Returns all supported window states by the portal + * as an enumertation of WindowState objects. + *

    + * The window states must at least include the + * standard window states MINIMIZED, NORMAL, MAXIMIZED. + * + * @return All supported window states by the portal + * as an enumertation of WindowState objects. + */ + + public java.util.Enumeration getSupportedWindowStates(); + + + /** + * Returns information about the portal like vendor, version, etc. + *

    + * The form of the returned string is servername/versionnumber. For + * example, the reference implementation Pluto may return the string + * Pluto/1.0. + *

    + * The portlet container may return other optional information after the + * primary string in parentheses, for example, Pluto/1.0 + * (JDK 1.3.1; Windows NT 4.0 x86). + * + * @return a String containing at least the portal name and version number + */ + + public java.lang.String getPortalInfo(); +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/Portlet.java b/fine-portlet-api/src/com/fr/third/javax/portlet/Portlet.java new file mode 100755 index 000000000..ba216d5d6 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/Portlet.java @@ -0,0 +1,183 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The Portlet interface is used by the portlet container to + * invoke the portlets. Every portlet has to implement this interface, + * either by directly implementing it, or by using an existing class + * implementing the Portlet interface. + *

    + * A portlet is a Java technology-based web component. It is managed by the portlet container and + * processes requests and generates dynamic content as response. Portlets are used by portals as + * pluggable user interface components. + *

    + * The content generated by a portlet is called a fragment. A fragment is a piece of + * markup (e.g. HTML, XHTML, WML) adhering to certain rules and can be aggregated + * with other fragments into a complete document. The content of a portlet is normally + * aggregated with the content of other portlets into the portal page. + *

    + * The portlet container instanciates portlets, manages their lifecycle + * and invoking them to process requests. The lifecycle consists of: + *

      + *
    • initializing the portlet using using the init method + *
    • request processsing + *
    • taking the portlet out of service using the destroy method + *
    + *

    + * Request processing is divided into two types: + *

      + *
    • action requests handled through the processAction method, + * to perform actions targeted to the portlet + *
    • render requests handled through the render method, + * to perform the render operation + *
    + */ +public interface Portlet +{ + + + + /** + * Called by the portlet container to indicate to a portlet that the + * portlet is being placed into service. + * + *

    The portlet container calls the init + * method exactly once after instantiating the portlet. + * The init method must complete successfully + * before the portlet can receive any requests. + * + *

    The portlet container cannot place the portlet into service + * if the init method + *

      + *
    1. Throws a PortletException + *
    2. Does not return within a time period defined by the portlet container. + *
    + * + * + * @param config a PortletConfig object + * containing the portlet's + * configuration and initialization parameters + * + * @exception PortletException if an exception has occurred that + * interferes with the portlet's normal + * operation. + * @exception UnavailableException if the portlet cannot perform the initialization at this time. + * + * + */ + + public void init(PortletConfig config) throws PortletException; + + + + + /** + * Called by the portlet container to allow the portlet to process + * an action request. This method is called if the client request was + * originated by a URL created (by the portlet) with the + * RenderResponse.createActionURL() method. + *

    + * Typically, in response to an action request, a portlet updates state + * based on the information sent in the action request parameters. + * In an action the portlet may: + *

      + *
    • issue a redirect + *
    • change its window state + *
    • change its portlet mode + *
    • modify its persistent state + *
    • set render parameters + *
    + *

    + * A client request triggered by an action URL translates into one + * action request and many render requests, one per portlet in the portal page. + * The action processing must be finished before the render requests + * can be issued. + * + * @param request + * the action request + * @param response + * the action response + * @exception PortletException + * if the portlet has problems fulfilling the + * request + * @exception UnavailableException + * if the portlet is unavailable to process the action at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception IOException + * if the streaming causes an I/O problem + */ + public void processAction (ActionRequest request, ActionResponse response) + throws PortletException, java.io.IOException; + + + + /** + * Called by the portlet container to allow the portlet to generate + * the content of the response based on its current state. + * + * @param request + * the render request + * @param response + * the render response + * + * @exception PortletException + * if the portlet has problems fulfilling the + * rendering request + * @exception UnavailableException + * if the portlet is unavailable to perform render at this time + * @exception PortletSecurityException + * if the portlet cannot fullfill this request because of security reasons + * @exception java.io.IOException + * if the streaming causes an I/O problem + */ + + public void render (RenderRequest request, RenderResponse response) + throws PortletException, java.io.IOException; + + + /** + * + * Called by the portlet container to indicate to a portlet that the + * portlet is being taken out of service. + *

    + * Before the portlet container calls the destroy method, it should + * allow any threads that are currently processing requests within + * the portlet object to complete execution. To avoid + * waiting forever, the portlet container can optionally wait for + * a predefined time before destroying the portlet object. + * + *

    This method enables the portlet to do the following: + *

      + *
    • clean up any resources that it holds (for example, memory, + * file handles, threads) + *
    • make sure that any persistent state is + * synchronized with the portlet current state in memory. + *
    + */ + + public void destroy(); +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletConfig.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletConfig.java new file mode 100755 index 000000000..65df87447 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletConfig.java @@ -0,0 +1,118 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + + +/** + * The PortletConfig interface provides the portlet with + * its configuration. The configuration holds information about the + * portlet that is valid for all users. The configuration is retrieved + * from the portlet definition in the deployment descriptor. + * The portlet can only read the configuration data. + *

    + * The configuration information contains the portlet name, the portlet + * initialization parameters, the portlet resource bundle and the portlet + * application context. + * + * @see Portlet + */ +public interface PortletConfig +{ + + + + /** + * Returns the name of the portlet. + *

    + * The name may be provided via server administration, assigned in the + * portlet application deployment descriptor with the portlet-name + * tag. + * + * @return the portlet name + */ + + public String getPortletName (); + + + /** + * Returns the PortletContext of the portlet application + * the portlet is in. + * + * @return a PortletContext object, used by the + * caller to interact with its portlet container + * + * @see PortletContext + */ + + public PortletContext getPortletContext (); + + + /** + * Gets the resource bundle for the given locale based on the + * resource bundle defined in the deployment descriptor + * with resource-bundle tag or the inlined resources + * defined in the deployment descriptor. + * + * @param locale the locale for which to retrieve the resource bundle + * + * @return the resource bundle for the given locale + * + */ + + public java.util.ResourceBundle getResourceBundle(java.util.Locale locale); + + + /** + * Returns a String containing the value of the named initialization parameter, + * or null if the parameter does not exist. + * + * @param name a String specifying the name + * of the initialization parameter + * + * @return a String containing the value + * of the initialization parameter + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public String getInitParameter(java.lang.String name); + + + /** + * Returns the names of the portlet initialization parameters as an + * Enumeration of String objects, or an empty Enumeration if the + * portlet has no initialization parameters. + * + * @return an Enumeration of String + * objects containing the names of the portlet + * initialization parameters, or an empty Enumeration if the + * portlet has no initialization parameters. + */ + + public java.util.Enumeration getInitParameterNames(); +} + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletContext.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletContext.java new file mode 100755 index 000000000..08277426e --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletContext.java @@ -0,0 +1,456 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + + +/** + * The PortletContext interface defines a portlet view + * of the portlet container. + * The PortletContext also makes resources available + * to the portlet. Using the context, a portlet can access + * the portlet log, and obtain URL references to resources. + * + *

    There is one context per "portlet application" per Java Virtual Machine. (A + * "portlet application" is a collection of portlets, servlets, and content installed + * under a specific subset of the server URL namespace, such as /catalog. + * They are possibly installed via a .war file.) + * As a web application, a portlet application also has a servlet context. + * The portlet context leverages most of its functionality from the + * servlet context of the portlet application. + *

    + * Attibutes stored in the context are global for all users and all + * components in the portlet application. + *

    + * In the case of a web + * application marked "distributed" in its deployment descriptor, there will + * be one context instance for each virtual machine. In this situation, the + * context cannot be used as a location to share global information (because + * the information is not truly global). Use an external resource, such as + * a database to achieve sharing on a global scope. + */ +public interface PortletContext +{ + + + /** + * Returns the name and version of the portlet container in which the + * portlet is running. + * + *

    + * The form of the returned string is containername/versionnumber. + * + * + * @return the string containing at least name and version number + */ + + public String getServerInfo (); + + /** + * Returns a {@link PortletRequestDispatcher} object that acts + * as a wrapper for the resource located at the given path. + * A PortletRequestDispatcher object can be used include the + * resource in a response. The resource can be dynamic or static. + * + *

    The pathname must begin with a slash ( / ) and is interpreted as relative + * to the current context root. + * + *

    This method returns null if the PortletContext + * cannot return a PortletRequestDispatcher + * for any reason. + * + * + * @param path a String specifying the pathname + * to the resource + * @return a PortletRequestDispatcher object + * that acts as a wrapper for the resource + * at the specified path. + * @see PortletRequestDispatcher + */ + + public PortletRequestDispatcher getRequestDispatcher(String path); + + + + /** + * Returns a {@link PortletRequestDispatcher} object that acts + * as a wrapper for the named servlet. + * + *

    Servlets (and also JSP pages) may be given names via server + * administration or via a web application deployment descriptor. + * + *

    This method returns null if the + * PortletContext cannot return a + * PortletRequestDispatcher for any reason. + * + * + * @param name a String specifying the name + * of a servlet to be wrapped + * + * @return a PortletRequestDispatcher object + * that acts as a wrapper for the named servlet + * + * @see PortletRequestDispatcher + * + */ + + public PortletRequestDispatcher getNamedDispatcher(String name); + + + /** + * Returns the resource located at the given path as an InputStream object. + * The data in the InputStream can be of any type or length. The method returns + * null if no resource exists at the given path. + *

    + * In order to access protected resources the path has to be prefixed with + * /WEB-INF/ (for example /WEB-INF/myportlet/myportlet.jsp). + * Otherwise, the direct path is used + * (for example /myportlet/myportlet.jsp). + * + * @param path the path to the resource + * + * @return the input stream + */ + public java.io.InputStream getResourceAsStream (String path); + + + + /** + * Returns the major version of the Portlet API that this portlet + * container supports. + * + * @return the major version + * + * @see #getMinorVersion() + */ + + public int getMajorVersion (); + + + /** + * Returns the minor version of the Portlet API that this portlet + * container supports. + * + * @return the minor version + * + * @see #getMajorVersion() + */ + + public int getMinorVersion (); + + + /** + * Returns the MIME type of the specified file, or null if + * the MIME type is not known. The MIME type is determined + * by the configuration of the portlet container and may be specified + * in a web application deployment descriptor. Common MIME + * types are text/html and image/gif. + * + * + * @param file a String specifying the name + * of a file + * + * @return a String specifying the MIME type of the file + * + */ + + public String getMimeType(String file); + + + /** + * Returns a String containing the real path + * for a given virtual path. For example, the path /index.html + * returns the absolute file path of the portlet container file system. + * + *

    The real path returned will be in a form + * appropriate to the computer and operating system on + * which the portlet container is running, including the + * proper path separators. This method returns null + * if the portlet container cannot translate the virtual path + * to a real path for any reason (such as when the content is + * being made available from a .war archive). + * + * @param path a String specifying a virtual path + * + * @return a String specifying the real path, + * or null if the transformation cannot be performed. + */ + + public String getRealPath(String path); + + + /** + * Returns a directory-like listing of all the paths to resources within + * the web application longest sub-path of which + * matches the supplied path argument. Paths indicating subdirectory paths + * end with a slash (/). The returned paths are all + * relative to the root of the web application and have a leading slash. + * For example, for a web application + * containing

    + * + * /welcome.html
    + * /catalog/index.html
    + * /catalog/products.html
    + * /catalog/offers/books.html
    + * /catalog/offers/music.html
    + * /customer/login.jsp
    + * /WEB-INF/web.xml
    + * /WEB-INF/classes/com.acme.OrderPortlet.class,

    + *
    + * + * getResourcePaths("/") returns + * {"/welcome.html", "/catalog/", "/customer/", "/WEB-INF/"}
    + * getResourcePaths("/catalog/") returns + * {"/catalog/index.html", "/catalog/products.html", "/catalog/offers/"}.
    + * + * @param path + * the partial path used to match the resources, which must start with a slash + * @return a Set containing the directory listing, or null if there + * are no resources in the web application of which the path + * begins with the supplied path. + */ + + public java.util.Set getResourcePaths(String path); + + + + /** + * Returns a URL to the resource that is mapped to a specified + * path. The path must begin with a slash (/) and is interpreted + * as relative to the current context root. + * + *

    This method allows the portlet container to make a resource + * available to portlets from any source. Resources + * can be located on a local or remote + * file system, in a database, or in a .war file. + * + *

    The portlet container must implement the URL handlers + * and URLConnection objects that are necessary + * to access the resource. + * + *

    This method returns null + * if no resource is mapped to the pathname. + * + *

    Some containers may allow writing to the URL returned by + * this method using the methods of the URL class. + * + *

    The resource content is returned directly, so be aware that + * requesting a .jsp page returns the JSP source code. + * Use a RequestDispatcher instead to include results of + * an execution. + * + *

    This method has a different purpose than + * java.lang.Class.getResource, + * which looks up resources based on a class loader. This + * method does not use class loaders. + * + * @param path a String specifying + * the path to the resource + * + * @return the resource located at the named path, + * or null if there is no resource + * at that path + * + * @exception MalformedURLException if the pathname is not given in + * the correct form + * + */ + + public java.net.URL getResource(String path) throws java.net.MalformedURLException; + + + /** + * Returns the portlet container attribute with the given name, + * or null if there is no attribute by that name. + * An attribute allows a portlet container to give the + * portlet additional information not + * already provided by this interface. + * A list of supported attributes can be retrieved using + * getAttributeNames. + * + *

    The attribute is returned as a java.lang.Object + * or some subclass. + * Attribute names should follow the same convention as package + * names. The Java Portlet API specification reserves names + * matching java.*, javax.*, + * and sun.*. + * + * + * @param name a String specifying the name + * of the attribute + * + * @return an Object containing the value + * of the attribute, or null + * if no attribute exists matching the given + * name + * + * @see #getAttributeNames + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public java.lang.Object getAttribute(java.lang.String name); + + + /** + * Returns an Enumeration containing the attribute names + * available within this portlet context, or an emtpy + * Enumeration if no attributes are available. Use the + * {@link #getAttribute} method with an attribute name + * to get the value of an attribute. + * + * @return an Enumeration of attribute names + * + * @see #getAttribute + */ + + public java.util.Enumeration getAttributeNames(); + + + /** + * Returns a String containing the value of the named context-wide + * initialization parameter, or null if the parameter does not exist. + * This method provides configuration information which may be useful for + * an entire "portlet application". + * + * @param name a String containing the name of the + * requested parameter + * + * @return a String containing the value + * of the initialization parameter, or + * null if the parameter does not exist. + * + * @see #getInitParameterNames + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public java.lang.String getInitParameter(java.lang.String name); + + + /** + * Returns the names of the context initialization parameters as an + * Enumeration of String objects, or an empty Enumeration if the context + * has no initialization parameters. + * + * @return an Enumeration of String + * objects containing the names of the context + * initialization parameters + * + * @see #getInitParameter + */ + + public java.util.Enumeration getInitParameterNames(); + + + /** + * Writes the specified message to a portlet log file, usually an event log. + * The name and type of the portlet log file is specific to the portlet container. + *

    + * This method mapps to the ServletContext.log method. + * The portlet container may in addition log this message in a + * portlet container specific log file. + * + * @param msg a String specifying the + * message to be written to the log file + */ + + public void log(java.lang.String msg); + + + /** + * Writes an explanatory message and a stack trace for a given + * Throwable exception to the portlet log file. + * The name and type of the portlet log file is specific to the + * portlet container, usually an event log. + *

    + * This method is mapped to the ServletContext.log method. + * The portlet container may in addition log this message in a + * portlet container specific log file. + * + * @param message a String that + * describes the error or exception + * @param throwable the Throwable error + * or exception + */ + + public void log(java.lang.String message, java.lang.Throwable throwable); + + + /** + * Removes the attribute with the given name from the portlet context. + * After removal, subsequent calls to + * {@link #getAttribute} to retrieve the attribute's value + * will return null. + * + * @param name a String specifying the name + * of the attribute to be removed + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void removeAttribute(java.lang.String name); + + + /** + * Binds an object to a given attribute name in this portlet context. + * If the name specified is already used for an attribute, this method + * removes the old attribute and binds the name to the new attribute. + *

    + * If a null value is passed, the effect is the same as calling + * removeAttribute(). + * + *

    Attribute names should follow the same convention as package + * names. The Java Portlet API specification reserves names + * matching java.*, javax.*, and + * sun.*. + * + * @param name a String specifying the name + * of the attribute + * @param object an Object representing the + * attribute to be bound + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void setAttribute(java.lang.String name, java.lang.Object object); + + + /** + * Returns the name of this portlet application correponding to this PortletContext as specified + * in the web.xml deployment descriptor for this web application by the + * display-name element. + * + * + * @return The name of the web application or null if no name has been declared in the deployment descriptor. + */ + + public String getPortletContextName(); + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletException.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletException.java new file mode 100755 index 000000000..44d697611 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletException.java @@ -0,0 +1,160 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + +/** + * The PortletException class defines a general exception + * that a portlet can throw when it is unable to perform its operation + * successfully. + */ + +public class PortletException extends java.lang.Exception +{ + + + private Throwable _cause; + + + /** + * Constructs a new portlet exception. + */ + + public PortletException () + { + super(); + } + + /** + * Constructs a new portlet exception with the given text. The + * portlet container may use the text write it to a log. + * + * @param text + * the exception text + */ + + public PortletException (String text) + { + super (text); + } + + /** + * Constructs a new portlet exception when the portlet needs to do + * the following: + *

      + *
    • throw an exception + *
    • include the "root cause" exception + *
    • include a description message + *
    + * + * @param text + * the exception text + * @param cause + * the root cause + */ + + public PortletException (String text, Throwable cause) + { + super(text); + _cause = cause; + // change this when going to jdk1.4: super (text, cause); + } + + /** + * Constructs a new portlet exception when the portlet needs to throw an + * exception. The exception's message is based on the localized message + * of the underlying exception. + * + * @param cause + * the root cause + */ + + public PortletException (Throwable cause) + { + _cause = cause; + // change this when going to jdk1.4: super (cause); + } + + /** + * Prints the stack trace of this exception to the standard error stream. + */ + public void printStackTrace() + { + this.printStackTrace(System.err); + } + + /** + * Prints the stack trace of this exception to the specified print stream. + * + * @param out the PrintStream to be used for output + */ + public void printStackTrace(java.io.PrintStream out) + { + this.printStackTrace(new java.io.PrintWriter(out, true)); + } + + /** + * Prints the stack trace of this exception to the specified print writer. + * + * @param out the PrintWriter to be used for output + */ + public void printStackTrace(java.io.PrintWriter out) + { + super.printStackTrace(out); + + if( getCause () != null ) { + out.println(); + out.print("Nested Exception is "); + getCause ().printStackTrace(out); + } + // change this when going tojdk1.4: + /* + super.printStackTrace(out); + + if( getRootCause () != null ) + { + out.println(); + out.print("Nested Exception is "); + getRootCause ().printStackTrace(out); + } + */ + } + + /** + * Returns the cause of this throwable or null if the + * cause is nonexistent or unknown. (The cause is the throwable that + * caused this throwable to get thrown.) + * + *

    This implementation returns the cause that was supplied via one of + * the constructors requiring a Throwable. + * + * @return the cause of this throwable or null if the + * cause is nonexistent or unknown. + */ + public Throwable getCause() { + return (_cause!=null ? _cause : null); + } + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletMode.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletMode.java new file mode 100755 index 000000000..4e078d3a4 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletMode.java @@ -0,0 +1,154 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The PortletMode class represents + * the possible modes that a portlet can assume. + *

    + * A portlet mode indicates the function a portlet is performing. + * Normally, portlets perform different tasks and create different + * content depending on the function they are currently performing. + * When invoking a portlet, the portlet container provides the + * current portlet mode to the portlet. + *

    + * Portlets can programmatically change their portlet + * mode when processing an action request. + *

    + * This class defines the default portlet modes EDIT, HELP, VIEW. + * Additional portlet modes may be defined by calling the constructor + * of this class. If a portal/portlet-container does not support a + * custom portlet mode defined in the portlet application deployment descriptor, + * the custom portlet mode will be ignored by the portal/portlet container. + */ +public class PortletMode +{ + + + /** + * The expected functionality for a portlet in VIEW portlet mode + * is to generate markup reflecting the current state of the portlet. + * For example, the VIEW portlet mode of a portlet may + * include one or more screens that the user can navigate and interact + * with, or it may consist of static content that does not require any + * user interaction. + *

    + * This mode must be supported by the portlet. + *

    + * The string value for this mode is "view". + */ + public final static PortletMode VIEW = new PortletMode ("view"); + + /** + * Within the EDIT portlet mode, a portlet should provide + * content and logic that lets a user customize the behavior of the portlet. + * The EDIT portlet mode may include one or more screens among which + * users can navigate to enter their customization data. + *

    + * Typically, portlets in EDIT portlet mode will + * set or update portlet preferences. + *

    + * This mode is optional. + *

    + * The string value for this mode is "edit". + */ + public final static PortletMode EDIT = new PortletMode ("edit"); + + /** + * When in HELP portlet mode, a portlet should provide help + * information about the portlet. This help information could be + * a simple help screen explaining the entire portlet in + * coherent text or it could be context-sensitive help. + *

    + * This mode is optional. + *

    + * The string value for this mode is "help". + */ + public final static PortletMode HELP = new PortletMode ("help"); + + + + + private String _name; + + + /** + * Creates a new portlet mode with the given name. + *

    + * Upper case letters in the name are converted to + * lower case letters. + * + * @param name The name of the portlet mode + */ + public PortletMode(String name) { + if (name==null) { + throw new IllegalArgumentException("PortletMode name can not be NULL"); + } + _name = name.toLowerCase(); + } + + + /** + * Returns a String representation of this portlet mode. + * Portlet mode names are always lower case names. + * + * @return String representation of this portlet mode + */ + + public String toString() { + return _name; + } + + /** + * Returns the hash code value for this portlet mode. + * The hash code is constructed by producing the + * hash value of the String value of this mode. + * + * @return hash code value for this portlet mode + */ + + public int hashCode() { + return _name.hashCode(); + } + + /** + * Compares the specified object with this portlet mode + * for equality. Returns true if the + * Strings equals method for the String + * representing the two portlet modes returns true. + * + * @param object the portlet mode to compare this portlet mode with + * + * @return true, if the specified object is equal with this portlet mode + */ + + public boolean equals(Object object) { + if ( object instanceof PortletMode ) + return _name.equals(((PortletMode) object)._name); + else + return false; + } +} + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletModeException.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletModeException.java new file mode 100755 index 000000000..4a71ec41d --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletModeException.java @@ -0,0 +1,107 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + +/** + * The PortletModeException is thrown when a portlet + * tries to use or set a portlet mode that is not supported by the current + * runtime environment or the portlet. + */ + +public class PortletModeException extends PortletException +{ + + + private transient PortletMode _mode = null; + + /** + * Constructs a new portlet mode exception with the given text and the + * portlet mode that caused this exception. The + * portlet container may use the text and portlet mode write it to a log. + * + * @param text + * the exception text + * @param mode + * the mode causing the exception + */ + + public PortletModeException (String text, PortletMode mode) + { + super (text); + _mode = mode; + } + + /** + * Constructs a new portlet mode exception when the portlet needs to do + * the following: + *

      + * throw an exception + *
    • include a message about the "root cause" that interfered + * with its normal operation + *
    • include a description message + *
    • include the portlet mode that caused this exception + *
    + * + * @param text + * the exception text + * @param cause + * the root cause + * @param mode + * the mode causing the exception + */ + + public PortletModeException (String text, Throwable cause, PortletMode mode) + { + super(text, cause); + _mode = mode; + } + + /** + * Constructs a new portlet mode exception when the portlet needs to throw an + * exception. The exception message is based on the localized message + * of the underlying exception and the portlet mode that caused this exception. + * + * @param cause + * the root cause + * @param mode + * the mode causing the exception + */ + + public PortletModeException (Throwable cause, PortletMode mode) + { + super(cause); + _mode = mode; + } + + /** + * Returns the unsupported portlet mode causing this exception. + * + * @return the portlet mode that caused this exception + */ + + public PortletMode getMode() + { + return _mode; + } +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletPreferences.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletPreferences.java new file mode 100755 index 000000000..b308f4017 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletPreferences.java @@ -0,0 +1,265 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + +/** + * The PortletPreferences interface allows the portlet to store + * configuration data. It is not the + * purpose of this interface to replace general purpose databases. + *

    + * There are two different types of preferences: + *

      + *
    • modifiable preferences - these preferences can be changed by the + * portlet in any standard portlet mode (EDIT, HELP, VIEW). + * Per default every preference is modifiable. + *
    • read-only preferences - these preferences cannot be changed by the + * portlet in any standard portlet mode, but may be changed by administrative modes. + * Preferences are read-only, if the are defined in the + * deployment descriptor with read-only set to true, + * or if the portlet container restricts write access. + *
    + *

    + * Changes are persisted when the store method is called. The store method + * can only be invoked within the scope of a processAction call. + * Changes that are not persisted are discarded when the + * processAction or render method ends. + */ +public interface PortletPreferences +{ + + + + + /** + * Returns true, if the value of this key cannot be modified by the user. + *

    + * Modifiable preferences can be changed by the + * portlet in any standard portlet mode (EDIT, HELP, VIEW). + * Per default every preference is modifiable. + *

    + * Read-only preferences cannot be changed by the + * portlet in any standard portlet mode, but inside of custom modes + * it may be allowed changing them. + * Preferences are read-only, if they are defined in the + * deployment descriptor with read-only set to true, + * or if the portlet container restricts write access. + * + * @return false, if the value of this key can be changed, or + * if the key is not known + * + * @exception java.lang.IllegalArgumentException + * if key is null. + */ + public boolean isReadOnly(String key); + + + + /** + * Returns the first String value associated with the specified key of this preference. + * If there is one or more preference values associated with the given key + * it returns the first associated value. + * If there are no preference values associated with the given key, or the + * backing preference database is unavailable, it returns the given + * default value. + * + * @param key key for which the associated value is to be returned + * @param def the value to be returned in the event that there is no + * value available associated with this key. + * + * @return the value associated with key, or def + * if no value is associated with key, or the backing + * store is inaccessible. + * + * @exception java.lang.IllegalArgumentException + * if key is null. (A + * null value for def is permitted.) + * + * @see #getValues(String, String[]) + */ + public String getValue(String key, String def); + + + /** + * Returns the String array value associated with the specified key in this preference. + * + *

    Returns the specified default if there is no value + * associated with the key, or if the backing store is inaccessible. + * + *

    If the implementation supports stored defaults and such a + * default exists and is accessible, it is used in favor of the + * specified default. + * + * + * @param key key for which associated value is to be returned. + * @param def the value to be returned in the event that this + * preference node has no value associated with key + * or the associated value cannot be interpreted as a String array, + * or the backing store is inaccessible. + * + * @return the String array value associated with + * key, or def if the + * associated value does not exist. + * + * @exception java.lang.IllegalArgumentException if key is null. (A + * null value for def is permitted.) + * + * @see #getValue(String,String) + */ + + public String[] getValues(String key, String[] def); + + + + /** + * Associates the specified String value with the specified key in this + * preference. + *

    + * The key cannot be null, but null values + * for the value parameter are allowed. + * + * @param key key with which the specified value is to be associated. + * @param value value to be associated with the specified key. + * + * @exception ReadOnlyException + * if this preference cannot be modified for this request + * @exception java.lang.IllegalArgumentException if key is null, + * or key.length() + * or value.length are to long. The maximum length + * for key and value are implementation specific. + * + * @see #setValues(String, String[]) + */ + public void setValue(String key, String value) throws ReadOnlyException; + + + + + /** + * Associates the specified String array value with the specified key in this + * preference. + *

    + * The key cannot be null, but null values + * in the values parameter are allowed. + * + * @param key key with which the value is to be associated + * @param values values to be associated with key + * + * @exception java.lang.IllegalArgumentException if key is null, or + * key.length() + * is to long or value.size is to large. The maximum + * length for key and maximum size for value are implementation specific. + * @exception ReadOnlyException + * if this preference cannot be modified for this request + * + * @see #setValue(String,String) + */ + + public void setValues(String key, String[] values) throws ReadOnlyException; + + + /** + * Returns all of the keys that have an associated value, + * or an empty Enumeration if no keys are + * available. + * + * @return an Enumeration of the keys that have an associated value, + * or an empty Enumeration if no keys are + * available. + */ + public java.util.Enumeration getNames(); + + /** + * Returns a Map of the preferences. + *

    + * The values in the returned Map are from type + * String array (String[]). + *

    + * If no preferences exist this method returns an empty Map. + * + * @return an immutable Map containing preference names as + * keys and preference values as map values, or an empty Map + * if no preference exist. The keys in the preference + * map are of type String. The values in the preference map are of type + * String array (String[]). + */ + + public java.util.Map getMap(); + + + /** + * Resets or removes the value associated with the specified key. + *

    + * If this implementation supports stored defaults, and there is such + * a default for the specified preference, the given key will be + * reset to the stored default. + *

    + * If there is no default available the key will be removed. + * + * @param key to reset + * + * @exception java.lang.IllegalArgumentException if key is null. + * @exception ReadOnlyException + * if this preference cannot be modified for this request + */ + + public void reset(String key) throws ReadOnlyException; + + + /** + * Commits all changes made to the preferences via the + * set methods in the persistent store. + *

    + * If this call returns succesfull, all changes are made + * persistent. If this call fails, no changes are made + * in the persistent store. This call is an atomic operation + * regardless of how many preference attributes have been modified. + *

    + * All changes made to preferences not followed by a call + * to the store method are discarded when the + * portlet finishes the processAction method. + *

    + * If a validator is defined for this preferences in the + * deployment descriptor, this validator is called before + * the actual store is performed to check wether the given + * preferences are vaild. If this check fails a + * ValidatorException is thrown. + * + * @exception java.io.IOException + * if changes cannot be written into + * the backend store + * @exception ValidatorException + * if the validation performed by the + * associated validator fails + * @exception java.lang.IllegalStateException + * if this method is called inside a render call + * + * @see PreferencesValidator + */ + + public void store() throws java.io.IOException, ValidatorException; + + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequest.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequest.java new file mode 100755 index 000000000..967d52f43 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequest.java @@ -0,0 +1,669 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The PortletRequest defines the base interface to provide client + * request information to a portlet. The portlet container uses two specialized + * versions of this interface when invoking a portlet, ActionRequest + * and RenderRequest. The portlet container creates these objects and + * passes them as arguments to the portlet's processAction and + * render methods. + * + * @see ActionRequest + * @see RenderRequest + */ +public interface PortletRequest +{ + + + /** Used to retrieve user information attributes with the + * getAttribute call. The user information is returned + * as a Map object. The portlet must define the + * user information attribute it is interested in inside the + * user-attribute section of the deployment descriptor. + * If an attribute is not supported + * by the current runtime system it will not show up in the user + * attribute map.
    + * If the user-attribute is supported by the runtime system, but not + * defined for a particular user, then for that user the attribute + * exists in the returned map and the attribute has a null value. + *

    + * If the user-attribute is not defined for the current user it + * will not show up in the Map. + *

    + * The value is javax.portlet.userinfo. + */ + public static final String USER_INFO = "javax.portlet.userinfo"; + + + /** + * String identifier for Basic authentication. Value "BASIC". + */ + public static final String BASIC_AUTH = "BASIC"; + + /** + * String identifier for Form based authentication. Value "FORM". + */ + public static final String FORM_AUTH = "FORM"; + + /** + * String identifier for Certification based authentication. Value "CLIENT_CERT". + */ + public static final String CLIENT_CERT_AUTH = "CLIENT_CERT"; + + /** + * String identifier for Digest based authentication. Value "DIGEST". + */ + public static final String DIGEST_AUTH = "DIGEST"; + + + /** + * Returns true, if the given window state is valid + * to be set for this portlet in the context + * of the current request. + * + * @param state window state to checked + * + * @return true, if it is valid for this portlet + * in this request to change to the + * given window state + * + */ + public boolean isWindowStateAllowed(WindowState state); + + + /** + * Returns true, if the given portlet mode is a valid + * one to set for this portlet in the context + * of the current request. + * + * @param mode portlet mode to check + * + * @return true, if it is valid for this portlet + * in this request to change to the + * given portlet mode + * + */ + + public boolean isPortletModeAllowed(PortletMode mode); + + + /** + * Returns the current portlet mode of the portlet. + * + * @return the portlet mode + */ + + public PortletMode getPortletMode (); + + + /** + * Returns the current window state of the portlet. + * + * @return the window state + */ + + public WindowState getWindowState (); + + + /** + * Returns the preferences object associated with the portlet. + * + * @return the portlet preferences + */ + public PortletPreferences getPreferences (); + + + /** + * Returns the current portlet session or, if there is no current session, + * creates one and returns the new session. + *

    + * Creating a new portlet session will result in creating + * a new HttpSession on which the portlet session is based on. + * + * @return the portlet session + */ + + public PortletSession getPortletSession (); + + + /** + * Returns the current portlet session or, if there is no current session + * and the given flag is true, creates one and returns + * the new session. + *

    + * If the given flag is false and there is no current + * portlet session, this method returns null. + *

    + * Creating a new portlet session will result in creating + * a new HttpSession on which the portlet session is based on. + * + * @param create + * true to create a new session,
    + * false to return null if there + * is no current session + * @return the portlet session + */ + + public PortletSession getPortletSession (boolean create); + + + /** + * Returns the value of the specified request property + * as a String. If the request did not include a property + * of the specified name, this method returns null. + *

    + * A portlet can access portal/portlet-container specific properties + * through this method and, if available, the + * headers of the HTTP client request. + *

    + * This method should only be used if the + * property has only one value. If the property might have + * more than one value, use {@link #getProperties}. + *

    + * If this method is used with a multivalued + * parameter, the value returned is equal to the first value + * in the Enumeration returned by getProperties. + * + * @param name a String specifying the + * property name + * + * @return a String containing the + * value of the requested + * property, or null + * if the request does not + * have a property of that name. + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public String getProperty(String name); + + + /** + * Returns all the values of the specified request property + * as a Enumeration of String objects. + *

    + * If the request did not include any propertys + * of the specified name, this method returns an empty + * Enumeration. + * The property name is case insensitive. You can use + * this method with any request property. + * + * @param name a String specifying the + * property name + * + * @return a Enumeration containing + * the values of the requested property. If + * the request does not have any properties of + * that name return an empty Enumeration. + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public java.util.Enumeration getProperties(String name); + + + /** + * + * Returns a Enumeration of all the property names + * this request contains. If the request has no + * properties, this method returns an empty Enumeration. + * + * + * @return an Enumeration of all the + * property names sent with this + * request; if the request has + * no properties, an empty Enumeration. + */ + + public java.util.Enumeration getPropertyNames(); + + + /** + * Returns the context of the calling portal. + * + * @return the context of the calling portal + */ + + public PortalContext getPortalContext(); + + + /** + * Returns the name of the authentication scheme used for the + * connection between client and portal, + * for example, BASIC_AUTH, CLIENT_CERT_AUTH, + * a custom one or null if there was no authentication. + * + * @return one of the static members BASIC_AUTH, + * FORM_AUTH, CLIENT_CERT_AUTH, + * DIGEST_AUTH (suitable for == comparison) + * indicating the authentication scheme, + * a custom one, or + * null if the request was + * not authenticated. + */ + + public java.lang.String getAuthType(); + + + /** + * Returns the context path which is the path prefix associated with the deployed + * portlet application. If the portlet application is rooted at the + * base of the web server URL namespace (also known as "default" context), + * this path must be an empty string. Otherwise, it must be the path the + * portlet application is rooted to, the path must start with a '/' and + * it must not end with a '/' character. + *

    + * To encode a URL the {@link PortletResponse#encodeURL} method must be used. + * + * @return a String specifying the + * portion of the request URL that indicates the context + * of the request + * + * @see PortletResponse#encodeURL + */ + + public String getContextPath(); + + + /** + * Returns the login of the user making this request, if the user + * has been authenticated, or null if the user has not been authenticated. + * + * @return a String specifying the login + * of the user making this request, or null + * if the user login is not known. + * + */ + + public java.lang.String getRemoteUser(); + + + /** + * Returns a java.security.Principal object containing the name of the + * current authenticated user. + * + * @return a java.security.Principal containing + * the name of the user making this request, or + * null if the user has not been + * authenticated. + */ + + public java.security.Principal getUserPrincipal(); + + + /** + * Returns a boolean indicating whether the authenticated user is + * included in the specified logical "role". Roles and role membership can be + * defined using deployment descriptors. If the user has not been + * authenticated, the method returns false. + * + * @param role a String specifying the name + * of the role + * + * @return a boolean indicating whether + * the user making this request belongs to a given role; + * false if the user has not been + * authenticated. + */ + + public boolean isUserInRole(java.lang.String role); + + + /** + * + * Returns the value of the named attribute as an Object, + * or null if no attribute of the given name exists. + *

    + * Attribute names should follow the same conventions as package + * names. This specification reserves names matching java.*, + * and javax.*. + *

    + * In a distributed portlet web application the Object + * needs to be serializable. + * + * @param name a String specifying the name of + * the attribute + * + * @return an Object containing the value + * of the attribute, or null if + * the attribute does not exist. + * + * @exception java.lang.IllegalArgumentException + * if name is null. + * + */ + + public Object getAttribute(String name); + + + /** + * Returns an Enumeration containing the + * names of the attributes available to this request. + * This method returns an empty Enumeration + * if the request has no attributes available to it. + * + * + * @return an Enumeration of strings + * containing the names + * of the request attributes, or an empty + * Enumeration if the request + * has no attributes available to it. + */ + + public java.util.Enumeration getAttributeNames(); + + + /** + * Returns the value of a request parameter as a String, + * or null if the parameter does not exist. Request parameters + * are extra information sent with the request. The returned parameter + * are "x-www-form-urlencoded" decoded. + *

    + * Only parameters targeted to the current portlet are accessible. + *

    + * This method should only be used if the + * parameter has only one value. If the parameter might have + * more than one value, use {@link #getParameterValues}. + *

    + * If this method is used with a multivalued + * parameter, the value returned is equal to the first value + * in the array returned by getParameterValues. + * + * + * + * @param name a String specifying the + * name of the parameter + * + * @return a String representing the + * single value of the parameter + * + * @see #getParameterValues + * + * @exception java.lang.IllegalArgumentException + * if name is null. + * + */ + + public String getParameter(String name); + + + /** + * + * Returns an Enumeration of String + * objects containing the names of the parameters contained + * in this request. If the request has + * no parameters, the method returns an + * empty Enumeration. + *

    + * Only parameters targeted to the current portlet are returned. + * + * + * @return an Enumeration of String + * objects, each String containing + * the name of a request parameter; or an + * empty Enumeration if the + * request has no parameters. + */ + + public java.util.Enumeration getParameterNames(); + + + /** + * Returns an array of String objects containing + * all of the values the given request parameter has, or + * null if the parameter does not exist. + * The returned parameters are "x-www-form-urlencoded" decoded. + *

    + * If the parameter has a single value, the array has a length + * of 1. + * + * + * @param name a String containing the name of + * the parameter the value of which is requested + * + * @return an array of String objects + * containing the parameter values. + * + * @see #getParameter + * + * @exception java.lang.IllegalArgumentException + * if name is null. + * + */ + + public String[] getParameterValues(String name); + + + /** + * Returns a Map of the parameters of this request. + * Request parameters are extra information sent with the request. + * The returned parameters are "x-www-form-urlencoded" decoded. + *

    + * The values in the returned Map are from type + * String array (String[]). + *

    + * If no parameters exist this method returns an empty Map. + * + * @return an immutable Map containing parameter names as + * keys and parameter values as map values, or an empty Map + * if no parameters exist. The keys in the parameter + * map are of type String. The values in the parameter map are of type + * String array (String[]). + */ + + public java.util.Map getParameterMap(); + + + /** + * Returns a boolean indicating whether this request was made + * using a secure channel between client and the portal, such as HTTPS. + * + * @return true, if the request was made using a secure channel. + */ + + public boolean isSecure(); + + + /** + * Stores an attribute in this request. + * + *

    Attribute names should follow the same conventions as + * package names. Names beginning with java.*, + * javax.*, and com.sun.* are + * reserved for use by Sun Microsystems. + *
    If the value passed into this method is null, + * the effect is the same as calling {@link #removeAttribute}. + * + * + * @param name a String specifying + * the name of the attribute + * + * @param o the Object to be stored + * + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void setAttribute(String name, Object o); + + + /** + * + * Removes an attribute from this request. This method is not + * generally needed, as attributes only persist as long as the request + * is being handled. + * + *

    Attribute names should follow the same conventions as + * package names. Names beginning with java.*, + * javax.*, and com.sun.* are + * reserved for use by Sun Microsystems. + * + * @param name a String specifying + * the name of the attribute to be removed + * + * + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void removeAttribute(String name); + + + /** + * + * Returns the session ID indicated in the client request. + * This session ID may not be a valid one, it may be an old + * one that has expired or has been invalidated. + * If the client request + * did not specify a session ID, this method returns + * null. + * + * @return a String specifying the session + * ID, or null if the request did + * not specify a session ID + * + * @see #isRequestedSessionIdValid + * + */ + + public String getRequestedSessionId(); + + + /** + * + * Checks whether the requested session ID is still valid. + * + * @return true if this + * request has an id for a valid session + * in the current session context; + * false otherwise + * + * @see #getRequestedSessionId + * @see #getPortletSession + */ + + public boolean isRequestedSessionIdValid(); + + + /** + * Returns the portal preferred content type for the response. + *

    + * The content type only includes the MIME type, not the + * character set. + *

    + * Only content types that the portlet has defined in its + * deployment descriptor are valid return values for + * this method call. If the portlet has defined + * '*' or '* / *' as supported content + * types, these may also be valid return values. + * + * @return preferred MIME type of the response + */ + + public String getResponseContentType(); + + + /** + * Gets a list of content types which the portal accepts for the response. + * This list is ordered with the most preferable types listed first. + *

    + * The content type only includes the MIME type, not the + * character set. + *

    + * Only content types that the portlet has defined in its + * deployment descriptor are valid return values for + * this method call. If the portlet has defined + * '*' or '* / *' as supported content + * types, these may also be valid return values. + * + * @return ordered list of MIME types for the response + */ + + public java.util.Enumeration getResponseContentTypes(); + + + /** + * Returns the preferred Locale in which the portal will accept content. + * The Locale may be based on the Accept-Language header of the client. + * + * @return the prefered Locale in which the portal will accept content. + */ + + public java.util.Locale getLocale(); + + + /** + * Returns an Enumeration of Locale objects indicating, in decreasing + * order starting with the preferred locale in which the portal will + * accept content for this request. + * The Locales may be based on the Accept-Language header of the client. + * + * @return an Enumeration of Locales, in decreasing order, in which + * the portal will accept content for this request + */ + + public java.util.Enumeration getLocales(); + + + /** + * Returns the name of the scheme used to make this request. + * For example, http, https, or ftp. + * Different schemes have different rules for constructing URLs, + * as noted in RFC 1738. + * + * @return a String containing the name + * of the scheme used to make this request + */ + + public String getScheme(); + + + /** + * Returns the host name of the server that received the request. + * + * @return a String containing the name + * of the server to which the request was sent + */ + + public String getServerName(); + + + /** + * Returns the port number on which this request was received. + * + * @return an integer specifying the port number + */ + + public int getServerPort(); + + + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequestDispatcher.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequestDispatcher.java new file mode 100755 index 000000000..f81379540 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletRequestDispatcher.java @@ -0,0 +1,80 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + +/** + * The PortletRequestDispatcher interface + * defines an object that receives requests from the client + * and sends them to the specified resources (such as a servlet, + * HTML file, or JSP file) on the server. The portlet + * container creates the PortletRequestDispatcher object, + * which is used as a wrapper around a server resource located + * at a particular path or given by a particular name. + * + */ + +public interface PortletRequestDispatcher { + + + /** + * + * Includes the content of a resource (servlet, JSP page, + * HTML file) in the response. In essence, this method enables + * programmatic server-side includes. + *

    + * The included servlet cannot set or change the response status code + * or set headers; any attempt to make a change is ignored. + * + * + * @param request a {@link RenderRequest} object + * that contains the client request + * + * @param response a {@link RenderResponse} object + * that contains the render response + * + * @exception PortletException if the included resource throws a ServletException, + * or other exceptions that are not Runtime- + * or IOExceptions. + * + * @exception java.io.IOException if the included resource throws this exception + * + * + */ + + public void include(RenderRequest request, RenderResponse response) + throws PortletException, java.io.IOException; + + + +} + + + + + + + + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletResponse.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletResponse.java new file mode 100755 index 000000000..217210ad5 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletResponse.java @@ -0,0 +1,113 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The PortletResponse defines the base interface to assist a + * portlet in creating and sending a response to the client. + * The portlet container uses two specialized versions of this interface + * when invoking a portlet, ActionResponse and + * RenderResponse. The portlet container creates these + * objects and passes them as arguments to the portlet's processAction + * and render methods. + * + * @see ActionResponse + * @see RenderResponse + */ +public interface PortletResponse +{ + + + + /** + * Adds a String property to an existing key to be returned to the portal. + *

    + * This method allows response properties to have multiple values. + *

    + * Properties can be used by portlets to provide vendor specific + * information to the portal. + * + * @param key the key of the property to be returned to the portal + * @param value the value of the property to be returned to the portal + * + * @exception java.lang.IllegalArgumentException + * if key is null. + */ + + public void addProperty(String key, String value); + + + /** + * Sets a String property to be returned to the portal. + *

    + * Properties can be used by portlets to provide vendor specific + * information to the portal. + *

    + * This method resets all properties previously added with the same key. + * + * @param key the key of the property to be returned to the portal + * @param value the value of the property to be returned to the portal + * + * @exception java.lang.IllegalArgumentException + * if key is null. + */ + + public void setProperty(String key, String value); + + + /** + * Returns the encoded URL of the resource, like servlets, + * JSPs, images and other static files, at the given path. + *

    + * Some portal/portlet-container implementation may require + * those URLs to contain implementation specific data encoded + * in it. Because of that, portlets should use this method to + * create such URLs. + *

    + * The encodeURL method may include the session ID + * and other portal/portlet-container specific information into the URL. + * If encoding is not needed, it returns the URL unchanged. + * + * @param path + * the URI path to the resource. This must be either + * an absolute URL (e.g. + * http://my.co/myportal/mywebap/myfolder/myresource.gif) + * or a full path URI (e.g. /myportal/mywebap/myfolder/myresource.gif). + * + * @exception java.lang.IllegalArgumentException + * if path doesn't have a leading slash or is not an absolute URL + * + * @return the encoded resource URL as string + */ + + public String encodeURL (String path); + + + + + +} + + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSecurityException.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSecurityException.java new file mode 100755 index 000000000..b5abedb63 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSecurityException.java @@ -0,0 +1,89 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + +/** + * A portlet should throw a PortletSecurityException + * when a call fails because of security reasons.
    + * Additionally it can be thrown by the portal/portlet-container. + */ + +public class PortletSecurityException extends PortletException +{ + + + private PortletSecurityException () + { + } + + /** + * Constructs a new security exception with the given text. The + * portlet container may use the text write it to a log. + * + * @param text + * the exception text + */ + + public PortletSecurityException (String text) + { + super (text); + } + + /** + * Constructs a new portlet security exception when the portlet needs to do + * the following: + *

      + * throw an exception + *
    • include a message about the "root cause" that interfered + * with its normal operation + *
    • include a description message + *
    + * + * @param text + * the exception text + * @param cause + * the root cause + */ + + public PortletSecurityException (String text, Throwable cause) + { + super(text, cause); + } + + /** + * Constructs a new portlet security exception when the portlet needs to throw an + * exception. The exception message is based on the localized message + * of the underlying exception. + * + * @param cause + * the root cause + */ + + public PortletSecurityException (Throwable cause) + { + super(cause); + } + + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSession.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSession.java new file mode 100755 index 000000000..d26efb5de --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSession.java @@ -0,0 +1,377 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + +/** + * The PortletSession interface provides a way to identify a user + * across more than one request and to store transient information about that user. + *

    + * A PortletSession is created per user client per portlet application. + *

    + * A portlet can bind an object attribute into a PortletSession by name. + * The PortletSession interface defines two scopes for storing objects: + *

      + *
    • APPLICATION_SCOPE + *
    • PORTLET_SCOPE + *
    + * All objects stored in the session using the APPLICATION_SCOPE + * must be available to all the portlets, servlets and + * JSPs that belongs to the same portlet application and that handles a + * request identified as being a part of the same session. + * Objects stored in the session using the PORTLET_SCOPE must be + * available to the portlet during requests for the same portlet window + * that the objects where stored from. Attributes stored in the + * PORTLET_SCOPE are not protected from other web components + * of the portlet application. They are just conveniently namespaced. + *

    + * The portlet session is based on the HttpSession. Therefore all + * HttpSession listeners do apply to the portlet session and + * attributes set in the portlet session are visible in the HttpSession + * and vice versa. + */ +public interface PortletSession +{ + + + /** + * This constant defines an application wide scope for the session attribute. + * APPLICATION_SCOPE session attributes enable Portlets + * within one portlet application to share data. + *

    + * Portlets may need to prefix attributes set in this scope with some + * ID, to avoid overwriting each other's attributes in the + * case where two portlets of the same portlet definition + * are created. + *

    + * Value: 0x01 + */ + public static final int APPLICATION_SCOPE = 0x01; + + /** + * This constant defines the scope of the session attribute to be + * private to the portlet and its included resources. + *

    + * Value: 0x02 + */ + public static final int PORTLET_SCOPE = 0x02; + + + + /** + * Returns the object bound with the specified name in this session + * under the PORTLET_SCOPE, or null if no + * object is bound under the name in that scope. + * + * @param name a string specifying the name of the object + * + * @return the object with the specified name for + * the PORTLET_SCOPE. + * + * @exception java.lang.IllegalStateException if this method is called on an + * invalidated session. + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public java.lang.Object getAttribute(java.lang.String name); + + + /** + * Returns the object bound with the specified name in this session, + * or null if no object is bound under the name in the given scope. + * + * @param name a string specifying the name of the object + * @param scope session scope of this attribute + * + * @return the object with the specified name + * + * @exception java.lang.IllegalStateException if this method is called on an + * invalidated session + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public java.lang.Object getAttribute(java.lang.String name,int scope); + + + /** + * Returns an Enumeration of String objects containing the names of + * all the objects bound to this session under the PORTLET_SCOPE, or an + * empty Enumeration if no attributes are available. + * + * @return an Enumeration of + * String objects specifying the + * names of all the objects bound to + * this session, or an empty Enumeration + * if no attributes are available. + * + * @exception java.lang.IllegalStateException if this method is called on an + * invalidated session + */ + + public java.util.Enumeration getAttributeNames(); + + + /** + * Returns an Enumeration of String objects containing the names of + * all the objects bound to this session in the given scope, or an + * empty Enumeration if no attributes are available in the + * given scope. + * + * @param scope session scope of the attribute names + * + * @return an Enumeration of + * String objects specifying the + * names of all the objects bound to + * this session, or an empty Enumeration + * if no attributes are available in the given scope. + * + * @exception java.lang.IllegalStateException if this method is called on an + * invalidated session + */ + + public java.util.Enumeration getAttributeNames(int scope); + + /** + * Returns the time when this session was created, measured in + * milliseconds since midnight January 1, 1970 GMT. + * + * @return a long specifying + * when this session was created, + * expressed in + * milliseconds since 1/1/1970 GMT + * + * @exception java.lang.IllegalStateException if this method is called on an + * invalidated session + */ + + public long getCreationTime(); + + + /** + * Returns a string containing the unique identifier assigned to this session. + * + * @return a string specifying the identifier + * assigned to this session + */ + + public java.lang.String getId(); + + + /** + * Returns the last time the client sent a request associated with this session, + * as the number of milliseconds since midnight January 1, 1970 GMT. + * + *

    Actions that your portlet takes, such as getting or setting + * a value associated with the session, do not affect the access + * time. + * + * @return a long + * representing the last time + * the client sent a request associated + * with this session, expressed in + * milliseconds since 1/1/1970 GMT + */ + + public long getLastAccessedTime(); + + + /** + * Returns the maximum time interval, in seconds, for which the portlet container + * keeps this session open between client accesses. After this interval, + * the portlet container invalidates the session. The maximum time + * interval can be set + * with the setMaxInactiveInterval method. + * A negative time indicates the session should never timeout. + * + * @return an integer specifying the number of + * seconds this session remains open + * between client requests + * + * @see #setMaxInactiveInterval + */ + + public int getMaxInactiveInterval(); + + + /** + * Invalidates this session (all scopes) and unbinds any objects bound to it. + *

    + * Invalidating the portlet session will result in invalidating the underlying + * HttpSession + * + * @exception java.lang.IllegalStateException if this method is called on a + * session which has already been invalidated + */ + + public void invalidate(); + + + + /** + * Returns true if the client does not yet know about the session or + * if the client chooses not to join the session. + * + * @return true if the + * server has created a session, + * but the client has not joined yet. + * + * @exception java.lang.IllegalStateException if this method is called on a + * session which has already been invalidated + * + */ + + public boolean isNew(); + + + /** + * Removes the object bound with the specified name under + * the PORTLET_SCOPE from + * this session. If the session does not have an object + * bound with the specified name, this method does nothing. + * + * @param name the name of the object to be + * removed from this session in the + * PORTLET_SCOPE. + * + * @exception java.lang.IllegalStateException + * if this method is called on a + * session which has been invalidated + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void removeAttribute(String name) ; + + + /** + * Removes the object bound with the specified name and the given scope from + * this session. If the session does not have an object + * bound with the specified name, this method does nothing. + * + * @param name the name of the object to be + * removed from this session + * @param scope session scope of this attribute + * + * @exception java.lang.IllegalStateException + * if this method is called on a + * session which has been invalidated + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void removeAttribute(String name, int scope) ; + + + /** + * Binds an object to this session under the PORTLET_SCOPE, using the name specified. + * If an object of the same name in this scope is already bound to the session, + * that object is replaced. + * + *

    After this method has been executed, and if the new object + * implements HttpSessionBindingListener, + * the container calls + * HttpSessionBindingListener.valueBound. The container then + * notifies any HttpSessionAttributeListeners in the web + * application. + *

    If an object was already bound to this session + * that implements HttpSessionBindingListener, its + * HttpSessionBindingListener.valueUnbound method is called. + * + *

    If the value is null, this has the same effect as calling + * removeAttribute(). + * + * + * @param name the name to which the object is bound under + * the PORTLET_SCOPE; + * this cannot be null. + * @param value the object to be bound + * + * @exception java.lang.IllegalStateException if this method is called on a + * session which has been invalidated + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void setAttribute(java.lang.String name, java.lang.Object value); + + + /** + * Binds an object to this session in the given scope, using the name specified. + * If an object of the same name in this scope is already bound to the session, + * that object is replaced. + * + *

    After this method has been executed, and if the new object + * implements HttpSessionBindingListener, + * the container calls + * HttpSessionBindingListener.valueBound. The container then + * notifies any HttpSessionAttributeListeners in the web + * application. + *

    If an object was already bound to this session + * that implements HttpSessionBindingListener, its + * HttpSessionBindingListener.valueUnbound method is called. + * + *

    If the value is null, this has the same effect as calling + * removeAttribute(). + * + * + * @param name the name to which the object is bound; + * this cannot be null. + * @param value the object to be bound + * @param scope session scope of this attribute + * + * @exception java.lang.IllegalStateException if this method is called on a + * session which has been invalidated + * @exception java.lang.IllegalArgumentException + * if name is null. + */ + + public void setAttribute(java.lang.String name, java.lang.Object value, int scope); + + + /** + * Specifies the time, in seconds, between client requests, before the + * portlet container invalidates this session. A negative time + * indicates the session should never timeout. + * + * @param interval An integer specifying the number + * of seconds + */ + + public void setMaxInactiveInterval(int interval); + + + /** + * Returns the portlet application context associated with this session. + * + * @return the portlet application context + */ + + public PortletContext getPortletContext (); + +} + + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSessionUtil.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSessionUtil.java new file mode 100755 index 000000000..b7d0f3b40 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletSessionUtil.java @@ -0,0 +1,90 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + +/** + * The PortletSessionUtil class helps identify and decode + * attributes in the PORTLET_SCOPE scope of the PortletSession + * when accessed through the HttpSession an from within calls to methods + * of the HttpSessionBindingListener interface. + */ +public class PortletSessionUtil +{ + + + private static final String PORTLET_SCOPE_NAMESPACE = "javax.portlet.p."; + + /** + * Returns the attribute name of an attribute in the + * PORTLET_SCOPE. If the attribute is in the + * APPLICATION_SCOPE it returns the attribute name unchanged. + * + * @param name a string specifying the name of the + * encoded portlet attribute + * + * @return the decoded attribute name + */ + + public static java.lang.String decodeAttributeName(java.lang.String name) + { + if (name.startsWith(PORTLET_SCOPE_NAMESPACE)) { + int index = name.indexOf('?'); + if (index>-1) { + name = name.substring(index+1); + } + } + return name; + } + + + /** + * Returns the portlet attribute scope from an encoded portlet + * attribute. + *
    Possible return values are: + *

      + *
    • PortletSession.APPLICATION_SCOPE
    • + *
    • PortletSession.PORTLET_SCOPE
    • + *
    + * + * @param name a string specifying the name of the + * encoded portlet attribute + * + * @return the decoded attribute scope + * @see PortletSession + */ + + public static int decodeScope(java.lang.String name) + { + int scope = PortletSession.APPLICATION_SCOPE; // APP + if (name.startsWith(PORTLET_SCOPE_NAMESPACE)) { + int index = name.indexOf('?'); + if (index>-1) { + scope = PortletSession.PORTLET_SCOPE; // PORTLET + } + } + return scope; + } +} + + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PortletURL.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletURL.java new file mode 100755 index 000000000..2a2d05d71 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PortletURL.java @@ -0,0 +1,211 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + + +/** + * The PortletURL interface represents a URL + * that reference the portlet itself. + *

    + * A PortletURL is created through the RenderResponse. + * Parameters, a portlet mode, a window state and a security level + * can be added to PortletURL objects. The PortletURL + * must be converted to a String in order to embed it into + * the markup generated by the portlet. + *

    + * There are two types of PortletURLs: + *

      + *
    • Action URLs, they are created with RenderResponse.createActionURL, and + * trigger an action request followed by a render request. + *
    • Render URLs, they are created with RenderResponse.createRenderURL, and + * trigger a render request. + *
    + *

    + * The string reprensentation of a PortletURL does not need to be a valid + * URL at the time the portlet is generating its content. It may contain + * special tokens that will be converted to a valid URL, by the portal, + * before the content is returned to the client. + */ +public interface PortletURL +{ + + + + + /** + * Indicates the window state the portlet should be in, if this + * portlet URL triggers a request. + *

    + * A URL can not have more than one window state attached to it. + * If more than one window state is set only the last one set + * is attached to the URL. + * + * @param windowState + * the portlet window state + * + * @exception WindowStateException + * if the portlet cannot switch to this state, + * because the portal does not support this state, the portlet has not + * declared in its deployment descriptor that it supports this state, or the current + * user is not allowed to switch to this state. + * The PortletRequest.isWindowStateAllowed() method can be used + * to check if the portlet can set a given window state. + * @see PortletRequest#isWindowStateAllowed + */ + public void setWindowState (WindowState windowState) + throws WindowStateException; + + + /** + * Indicates the portlet mode the portlet must be in, if this + * portlet URL triggers a request. + *

    + * A URL can not have more than one portlet mode attached to it. + * If more than one portlet mode is set only the last one set + * is attached to the URL. + * + * @param portletMode + * the portlet mode + * + * @exception PortletModeException + * if the portlet cannot switch to this mode, + * because the portal does not support this mode, the portlet has not + * declared in its deployment descriptor that it supports this mode for the current markup, + * or the current user is not allowed to switch to this mode. + * The PortletRequest.isPortletModeAllowed() method can be used + * to check if the portlet can set a given portlet mode. + * @see PortletRequest#isPortletModeAllowed + */ + public void setPortletMode (PortletMode portletMode) + throws PortletModeException; + + + /** + * Sets the given String parameter to this URL. + *

    + * This method replaces all parameters with the given key. + *

    + * The PortletURL implementation 'x-www-form-urlencoded' encodes + * all parameter names and values. Developers should not encode them. + *

    + * A portlet container may prefix the attribute names internally + * in order to preserve a unique namespace for the portlet. + * + * @param name + * the parameter name + * @param value + * the parameter value + * + * @exception java.lang.IllegalArgumentException + * if name or value are null. + */ + + public void setParameter (String name, String value); + + + /** + * Sets the given String array parameter to this URL. + *

    + * This method replaces all parameters with the given key. + *

    + * The PortletURL implementation 'x-www-form-urlencoded' encodes + * all parameter names and values. Developers should not encode them. + *

    + * A portlet container may prefix the attribute names internally + * in order to preserve a unique namespace for the portlet. + * + * @param name + * the parameter name + * @param values + * the parameter values + * + * @exception java.lang.IllegalArgumentException + * if name or values are null. + */ + + public void setParameter (String name, String[] values); + + + /** + * Sets a parameter map for this URL. + *

    + * All previously set parameters are cleared. + *

    + * The PortletURL implementation 'x-www-form-urlencoded' encodes + * all parameter names and values. Developers should not encode them. + *

    + * A portlet container may prefix the attribute names internally, + * in order to preserve a unique namespace for the portlet. + * + * @param parameters Map containing parameter names for + * the render phase as + * keys and parameter values as map + * values. The keys in the parameter + * map must be of type String. The values + * in the parameter map must be of type + * String array (String[]). + * + * @exception java.lang.IllegalArgumentException + * if parameters is null, if + * any of the key/values in the Map are null, + * if any of the keys is not a String, or if any of + * the values is not a String array. + */ + + public void setParameters(java.util.Map parameters); + + + /** + * Indicated the security setting for this URL. + *

    + * Secure set to true indicates that the portlet requests + * a secure connection between the client and the portlet window for + * this URL. Secure set to false indicates that the portlet + * does not need a secure connection for this URL. If the security is not + * set for a URL, it will stay the same as the current request. + * + * @param secure true, if portlet requests to have a secure connection + * between its portlet window and the client; false, if + * the portlet does not require a secure connection. + * + * @throws PortletSecurityException if the run-time environment does + * not support the indicated setting + */ + + public void setSecure (boolean secure) throws PortletSecurityException; + + + /** + * Returns the portlet URL string representation to be embedded in the + * markup.
    + * Note that the returned String may not be a valid URL, as it may + * be rewritten by the portal/portlet-container before returning the + * markup to the client. + * + * @return the encoded URL as a string + */ + + public String toString (); +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/PreferencesValidator.java b/fine-portlet-api/src/com/fr/third/javax/portlet/PreferencesValidator.java new file mode 100755 index 000000000..95673b6bc --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/PreferencesValidator.java @@ -0,0 +1,53 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The PreferencesValidator allows to validate the set of + * preferences of the associated portlet just before they are + * stored in the persistent store. + *

    + * The portlet container invokes the validate method as + * part of the invocation of the store method of the + * PortletPreferences. + */ +public interface PreferencesValidator +{ + + + /** + * If the preferences values are successfully validated the call to this method + * must finish gracefully. Otherwise it must throw a ValidatorException. + * + * @param preferences preferences to validate + * + * @throws ValidatorException if the given preferences contains invalid + * settings + * + */ + + public void validate(PortletPreferences preferences) + throws ValidatorException; +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/ReadOnlyException.java b/fine-portlet-api/src/com/fr/third/javax/portlet/ReadOnlyException.java new file mode 100755 index 000000000..eb700278e --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/ReadOnlyException.java @@ -0,0 +1,88 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + +/** + * The ReadOnlyException is thrown when a portlet tries + * to change the value for a read-only preference attribute. + */ + +public class ReadOnlyException extends PortletException +{ + + + private ReadOnlyException () + { + } + + /** + * Constructs a new read-only exception with the given text. The + * portlet container may use the text write it to a log. + * + * @param text + * the exception text + */ + + public ReadOnlyException (String text) + { + super (text); + } + + /** + * Constructs a new read-only exception when the portlet needs to do + * the following: + *

      + * throw an exception + *
    • include a message about the "root cause" that interfered + * with its normal operation + *
    • include a description message + *
    + * + * @param text + * the exception text + * @param cause + * the root cause + */ + + public ReadOnlyException (String text, Throwable cause) + { + super(text, cause); + } + + /** + * Constructs a new read-only exception when the portlet needs to throw an + * exception. The exception message is based on the localized message + * of the underlying exception. + * + * @param cause + * the root cause + */ + + public ReadOnlyException (Throwable cause) + { + super(cause); + } + + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/RenderRequest.java b/fine-portlet-api/src/com/fr/third/javax/portlet/RenderRequest.java new file mode 100755 index 000000000..e6e025ebe --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/RenderRequest.java @@ -0,0 +1,43 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The RenderRequest represents the request sent to the portlet + * to handle a render. + * It extends the PortletRequest interface to provide render request + * information to portlets.
    + * The portlet container creates a RenderRequest object and + * passes it as argument to the portlet's render method. + * + * @see PortletRequest + * @see ActionRequest + */ +public interface RenderRequest extends PortletRequest +{ + + + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/RenderResponse.java b/fine-portlet-api/src/com/fr/third/javax/portlet/RenderResponse.java new file mode 100755 index 000000000..60ea6b781 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/RenderResponse.java @@ -0,0 +1,342 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The RenderResponse defines an object to assist a portlet in + * sending a response to the portal. + * It extends the PortletResponse interface to provide specific + * render response functionality to portlets.
    + * The portlet container creates a RenderResponse object and + * passes it as argument to the portlet's render method. + * + * @see RenderRequest + * @see PortletResponse + */ +public interface RenderResponse extends PortletResponse +{ + + + /** + * Property to set the expiration time in seconds for this + * response using the setProperty method. + *

    + * If the expiration value is set to 0, caching is disabled + * for this portlet; if the value is set to -1, + * the cache does not expire. + *

    + * The value is "portlet.expiration-cache". + */ + public static final String EXPIRATION_CACHE = "portlet.expiration-cache"; + + /** + * Returns the MIME type that can be used to contribute + * markup to the render response. + *

    + * If no content type was set previously using the {@link #setContentType} method + * this method retuns null. + * + * @see #setContentType + * + * @return the MIME type of the response, or null + * if no content type is set + */ + + public String getContentType (); + + + /** + * Creates a portlet URL targeting the portlet. If no portlet mode, + * window state or security modifier is set in the PortletURL the + * current values are preserved. If a request is triggered by the + * PortletURL, it results in a render request. + *

    + * The returned URL can be further extended by adding + * portlet-specific parameters and portlet modes and window states. + *

    + * The created URL will per default not contain any parameters + * of the current render request. + * + * @return a portlet render URL + */ + public PortletURL createRenderURL (); + + + /** + * Creates a portlet URL targeting the portlet. If no portlet mode, + * window state or security modifier is set in the PortletURL the + * current values are preserved. If a request is triggered by the + * PortletURL, it results in an action request. + *

    + * The returned URL can be further extended by adding + * portlet-specific parameters and portlet modes and window states. + *

    + * The created URL will per default not contain any parameters + * of the current render request. + * + * @return a portlet action URL + */ + public PortletURL createActionURL (); + + + + /** + * The value returned by this method should be prefixed or appended to + * elements, such as JavaScript variables or function names, to ensure + * they are unique in the context of the portal page. + * + * @return the namespace + */ + + public String getNamespace (); + + + + /** + * This method sets the title of the portlet. + *

    + * The value can be a text String + * + * @param title portlet title as text String or resource URI + */ + + public void setTitle(String title); + + + + + /** + * Sets the MIME type for the render response. The portlet must + * set the content type before calling {@link #getWriter} or + * {@link #getPortletOutputStream}. + *

    + * Calling setContentType after getWriter + * or getOutputStream does not change the content type. + * + * @param type the content MIME type + * + * @throws java.lang.IllegalArgumentException + * if the given type is not in the list returned + * by PortletRequest.getResponseContentTypes + * + * @see RenderRequest#getResponseContentTypes + * @see #getContentType + */ + + public void setContentType(String type); + + + /** + * Returns the name of the charset used for + * the MIME body sent in this response. + * + *

    + * Before calling this method the content type of the + * render response must be set using the {@link #setContentType} + * method. + *

    + * Either this method or {@link #getPortletOutputStream} may be + * called to write the body, not both. + * + * @return a PrintWriter object that + * can return character data to the portal + * + * @exception java.io.IOException + * if an input or output exception occurred + * @exception java.lang.IllegalStateException + * if the getPortletOutputStream method + * has been called on this response, + * or if no content type was set using the + * setContentType method. + * + * @see #setContentType + * @see #getPortletOutputStream + */ + + public java.io.PrintWriter getWriter() throws java.io.IOException; + + + /** + * Returns the locale assigned to the response. + * + * @return Locale of this response + */ + + public java.util.Locale getLocale(); + + + /** + * Sets the preferred buffer size for the body of the response. + * The portlet container will use a buffer at least as large as + * the size requested. + *

    + * This method must be called before any response body content is + * written; if content has been written, or the portlet container + * does not support buffering, this method may throw an + * IllegalStateException. + * + * @param size the preferred buffer size + * + * @exception java.lang.IllegalStateException + * if this method is called after + * content has been written, or the + * portlet container does not support buffering + * + * @see #getBufferSize + * @see #flushBuffer + * @see #isCommitted + * @see #reset + */ + + public void setBufferSize(int size); + + + /** + * Returns the actual buffer size used for the response. If no buffering + * is used, this method returns 0. + * + * @return the actual buffer size used + * + * @see #setBufferSize + * @see #flushBuffer + * @see #isCommitted + * @see #reset + */ + + public int getBufferSize(); + + + + /** + * Forces any content in the buffer to be written to the client. A call + * to this method automatically commits the response. + * + * @exception java.io.IOException if an error occured when writing the output + * + * @see #setBufferSize + * @see #getBufferSize + * @see #isCommitted + * @see #reset + */ + + public void flushBuffer() throws java.io.IOException; + + + /** + * Clears the content of the underlying buffer in the response without + * clearing properties set. If the response has been committed, + * this method throws an IllegalStateException. + * + * @exception IllegalStateException if this method is called after + * response is comitted + * + * @see #setBufferSize + * @see #getBufferSize + * @see #isCommitted + * @see #reset + */ + + public void resetBuffer(); + + + /** + * Returns a boolean indicating if the response has been + * committed. + * + * @return a boolean indicating if the response has been + * committed + * + * @see #setBufferSize + * @see #getBufferSize + * @see #flushBuffer + * @see #reset + */ + + public boolean isCommitted(); + + + /** + * Clears any data that exists in the buffer as well as the properties set. + * If the response has been committed, this method throws an + * IllegalStateException. + * + * @exception java.lang.IllegalStateException if the response has already been + * committed + * + * @see #setBufferSize + * @see #getBufferSize + * @see #flushBuffer + * @see #isCommitted + */ + + public void reset(); + + + /** + * Returns a OutputStream suitable for writing binary + * data in the response. The portlet container does not encode the + * binary data. + *

    + * Before calling this method the content type of the + * render response must be set using the {@link #setContentType} + * method. + *

    + * Calling flush() on the OutputStream commits the response. + *

    + * Either this method or {@link #getWriter} may be called to write the body, not both. + * + * @return a OutputStream for writing binary data + * + * @exception java.lang.IllegalStateException if the getWriter method + * has been called on this response, or + * if no content type was set using the + * setContentType method. + * + * @exception java.io.IOException if an input or output exception occurred + * + * @see #setContentType + * @see #getWriter + */ + + public java.io.OutputStream getPortletOutputStream() throws java.io.IOException; + +} + + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/UnavailableException.java b/fine-portlet-api/src/com/fr/third/javax/portlet/UnavailableException.java new file mode 100755 index 000000000..e1577355f --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/UnavailableException.java @@ -0,0 +1,134 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + +/** + * The portlet should throw the UnavailableException when + * the portlet is either temporarily or permanently unavailable to handle requests. + * + **/ + +public class UnavailableException extends PortletException +{ + + + private boolean permanent; // needs admin action? + private int seconds; // unavailability estimate + + + /** + * + * Constructs a new exception with a descriptive + * message indicating that the portlet is permanently + * unavailable. + * + * @param text a String specifying the + * descriptive message + * + */ + + public UnavailableException(String text) { + super(text); + + permanent = true; + } + + /** + * Constructs a new exception with a descriptive message + * indicating that the portlet is temporarily unavailable + * and giving an estimate of how long it will be unavailable. + * + *

    In some cases, the portlet cannot make an estimate. For + * example, the portlet might know that a server it needs is + * not running, but it might not be able to report how long it will take + * to be restored to functionality. This can be indicated with + * a negative or zero value for the seconds argument. + * + * @param text a String specifying the + * descriptive message. This message can be written + * to a log file or displayed for the user. + * + * @param seconds an integer specifying the number of seconds + * for which the portlet expects to be unavailable; if + * this is zero or negative, it indicates that the portlet + * cannot make an estimate. + * + */ + + public UnavailableException(String text, int seconds) { + super(text); + + if (seconds <= 0) + this.seconds = -1; + else + this.seconds = seconds; + + permanent = false; + } + + /** + * + * Returns a boolean indicating + * whether the portlet is permanently unavailable. + * If so, something is wrong with the portlet, and the + * system administrator must take some corrective action. + * + * @return true if the portlet is + * permanently unavailable; false + * if the portlet is temporarily + * unavailable. + * + */ + + public boolean isPermanent() { + return permanent; + } + + + /** + * Returns the time in seconds for which the portlet can be expected to + * be unavailable. + *

    + * If the portlet is called again while it is still unavailable, it + * indicates the same time estimate. No effort is + * made to correct for the time elapsed since the exception was + * first reported. + *

    + * If this method returns zero or a negative number, the portlet + * is permanently unavailable or cannot provide an estimate of + * how long it will be unavailable. + * + * @return an integer specifying the number of seconds + * the portlet will be temporarily unavailable, + * or zero or a negative number if the portlet is permanently + * unavailable or cannot make an estimate. + * + */ + + public int getUnavailableSeconds() { + return permanent ? -1 : seconds; + } + + +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/ValidatorException.java b/fine-portlet-api/src/com/fr/third/javax/portlet/ValidatorException.java new file mode 100755 index 000000000..f26f14f2c --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/ValidatorException.java @@ -0,0 +1,132 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; + +/** + * The ValidatorException is thrown by the + * validate method of a PreferencesValidator when + * the validation of a preference failed. + */ + +public class ValidatorException extends PortletException +{ + + + private transient ArrayList failedKeyVector = new ArrayList(); + + private ValidatorException () + { + } + + /** + * Constructs a new validator exception with the given text. The + * portlet container may use the text write it to a log. + *

    + * The collection of failed keys may contain all failed keys, only the + * first key that failed validation, or may be null. + * + * @param text + * the exception text + * @param failedKeys + * keys that failed the validation; may be null + */ + + public ValidatorException (String text, Collection failedKeys) + { + super (text); + if ( failedKeys != null ) + failedKeyVector.addAll(failedKeys); + } + + /** + * Constructs a new portlet validator exception. + * Used, when the portlet needs to do one of the following: + *

      + * throw an exception + *
    • include a message about the "root cause" that interfered + * with its normal operation + *
    • include a description message + *
    + *

    + * The Collection of failed keys may contain all failed keys, only the + * first key that failed validation, or may be null. + * + * @param text + * the exception text + * @param cause + * the root cause + * @param failedKeys + * keys that failed the validation; may be null + */ + + public ValidatorException (String text, Throwable cause, Collection failedKeys) + { + super(text, cause); + if ( failedKeys != null ) + failedKeyVector.addAll(failedKeys); + } + + /** + * Constructs a new portlet validator exception when the portlet needs to throw an + * exception. The exception message is based on the localized message + * of the underlying exception. + *

    + * The Collection of failed keys may contain all failed keys, only the + * first key that failed validation, or may be null. + * + * @param cause + * the root cause + * @param failedKeys + * keys that failed the validation; may be null + */ + + public ValidatorException (Throwable cause, Collection failedKeys) + { + super(cause); + if ( failedKeys != null ) + failedKeyVector.addAll(failedKeys); + } + + + /** + * Returns the keys that failed the validation. + *

    + * The Enumeration of failed keys may contain all failed keys, only the + * first key that failed validation, or an empty + * Enumeration if no failed keys are available. + * + * @return the keys that failed validation, or an empty + * Enumeration if no failed keys are available. + */ + + public Enumeration getFailedKeys() + { + return Collections.enumeration(failedKeyVector); + } +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/WindowState.java b/fine-portlet-api/src/com/fr/third/javax/portlet/WindowState.java new file mode 100755 index 000000000..37f7f2b52 --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/WindowState.java @@ -0,0 +1,135 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + + +/** + * The WindowState class represents + * the possible window states that a portlet window can assume. + *

    + * This class defines a standard set of the most basic portlet window states. + * Additional window states may be defined by calling the constructor of + * this class. If a portal/portlet-container does not support a + * custom window state defined in the portlet application deployment descriptor, + * the custom window state will be ignored by the portal/portlet container. + */ + +public class WindowState +{ + + + /** + * The NORMAL window state indicates that a portlet + * may be sharing the page with other portlets. It may also + * indicate that the target device has limited display capabilities. + * Therefore, a portlet should restrict the size of its rendered + * output in this window state. + *

    + * The string value for this state is "normal". + */ + public final static WindowState NORMAL = new WindowState ("normal"); + + /** + * The MAXIMIZED window state is an indication + * that a portlet may be the only portlet being rendered in the + * portal page, or that the portlet has more space compared to other portlets + * in the portal page. A portlet may generate richer content + * when its window state is MAXIMIZED. + *

    + * The string value for this state is "maximized". + */ + public final static WindowState MAXIMIZED = new WindowState ("maximized"); + + /** + * When a portlet is in MINIMIZED window state, + * the portlet should only render minimal output or no output at all. + *

    + * The string value for this state is "minimized". + */ + public final static WindowState MINIMIZED = new WindowState ("minimized"); + + + + private String _name; + + + /** + * Creates a new window state with the given name. + *

    + * Upper case letters in the name are converted to + * lower case letters. + * + * @param name The name of the portlet mode + */ + public WindowState(String name) { + if (name==null) { + throw new IllegalArgumentException("WindowState name can not be NULL"); + } + _name = name.toLowerCase(); + } + + /** + * Returns a String representation of this window state. + * Window state names are always lower case names. + * + * @return String representation of this window state. + */ + + public String toString() { + return _name; + } + + + /** + * Returns the hash code value for this window state. + * The hash code is constructed by producing the + * hash value of the String value of this window state. + * + * @return hash code value for this window state + */ + + public int hashCode() { + return _name.hashCode(); + } + + + /** + * Compares the specified object with this window state + * for equality. Returns true if the + * Strings equals method for the String + * representing the two window states returns true. + * + * @param object the window state to compare this window state with. + * + * @return true, if the specified object is equal with this window state. + */ + + public boolean equals(Object object) { + if ( object instanceof WindowState ) + return _name.equals(((WindowState) object)._name); + else + return false; + } +} + diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/WindowStateException.java b/fine-portlet-api/src/com/fr/third/javax/portlet/WindowStateException.java new file mode 100755 index 000000000..4c07301ee --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/WindowStateException.java @@ -0,0 +1,105 @@ +/** + * 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. + */ + +/** + * This source code implements specifications defined by the Java + * Community Process. In order to remain compliant with the specification + * DO NOT add / change / or delete method signatures! + */ + +package com.fr.third.javax.portlet; + +/** + ** The WindowStateException is thrown when a portlet + ** tries to use a window state that is not supported by the current + ** runtime environment or the portlet. + **/ + +public class WindowStateException extends PortletException +{ + + + private transient WindowState _state = null; + + /** + * Constructs a new portlet state exception with the given text. The + * portlet container may use the text write it to a log. + * + * @param text + * the exception text + * @param state + * the state causing the exception + */ + + public WindowStateException (String text, WindowState state) + { + super (text); + _state = state; + } + + /** + * Constructs a new portlet state exception when the portlet needs to do + * the following: + *

      + * throw an exception + *
    • include a message about the "root cause" that interfered + * with its normal operation + *
    • include a description message + *
    + * + * @param text + * the exception text + * @param cause + * the root cause + * @param state + * the state causing the exception + */ + + public WindowStateException (String text, Throwable cause, WindowState state) + { + super(text, cause); + _state = state; + } + + /** + * Constructs a new portlet state exception when the portlet needs to throw an + * exception. The exception message is based on the localized message + * of the underlying exception. + * + * @param cause + * the root cause + * @param state + * the state causing the exception + */ + + public WindowStateException (Throwable cause, WindowState state) + { + super(cause); + _state = state; + } + + /** + * Returns the portlet state causing this exception. + * + * @return the window state causing this exception + */ + + public WindowState getState() + { + return _state; + } +} diff --git a/fine-portlet-api/src/com/fr/third/javax/portlet/package-info.java b/fine-portlet-api/src/com/fr/third/javax/portlet/package-info.java new file mode 100755 index 000000000..d87eaf23c --- /dev/null +++ b/fine-portlet-api/src/com/fr/third/javax/portlet/package-info.java @@ -0,0 +1,38 @@ +/** + * 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. + */ + +/** + * The com.fr.third.javax.portlet package defines the API for portlets. + *

    + * A portlet is a Java technology based web component, managed by a portlet container, + * that processes requests and generates dynamic content. Portlets provide a presentation + * layer to Information Systems. + *

    + * Portlets generate fragments of markup (e.g. HTML, XHTML, WML). A portal combines markup + * fragments generated by different portlets into a portal page. + *

    + * A portlet container manages the lifecyle of portlets. It also provides the required runtime environment. + *

    + * Portlets are bundled in Portlet Applications as web applications using the WAR file format. + * A portlet application consists of two deployment descriptors: one to specify + * the web application resources (web.xml) and one to specify the portlet resources + * (portlet.xml). The portlet.xml deployment descriptor must conform to the schema identified + * by the namespace http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd. + *

    + */ + +package com.fr.third.javax.portlet; \ No newline at end of file

    See RFC 2047 + * for more information about character encoding and MIME. + * + * @return a String specifying the + * name of the charset, for + * example, ISO-8859-1 + * + */ + + public String getCharacterEncoding(); + + + /** + * Returns a PrintWriter object that can send character + * text to the portal. + *