Browse Source

Simple dumb HTTP server for Git

This is a simple HTTP server that provides the minimum server side
support required for dumb (non-git aware) transport clients.

We produce the info/refs and objects/info/packs file on the fly
from the local repository state, but otherwise serve data as raw
files from the on-disk structure.

In the future we could better optimize the FileSender class and the
servlets that use it to take advantage of direct file to network
APIs in more advanced servlet containers like Jetty.

Our glue package borrows the idea of a micro embedded DSL from
Google Guice and uses it to configure a collection of Filters
and HttpServlets, all of which are matched against requests using
regular expressions.  If a subgroup exists in the pattern, it is
extracted and used for the path info component of the request.

Change-Id: Ia0f1a425d07d035e344ae54faf8aeb04763e7487
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
tags/v0.7.0
Shawn O. Pearce 14 years ago
parent
commit
5e33a1de83
42 changed files with 4000 additions and 17 deletions
  1. 7
    0
      org.eclipse.jgit.http.server/.classpath
  2. 125
    0
      org.eclipse.jgit.http.server/.fbprefs
  3. 2
    0
      org.eclipse.jgit.http.server/.gitignore
  4. 28
    0
      org.eclipse.jgit.http.server/.project
  5. 3
    0
      org.eclipse.jgit.http.server/.settings/org.eclipse.core.resources.prefs
  6. 3
    0
      org.eclipse.jgit.http.server/.settings/org.eclipse.core.runtime.prefs
  7. 334
    0
      org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs
  8. 61
    0
      org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.ui.prefs
  9. 21
    0
      org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
  10. 5
    0
      org.eclipse.jgit.http.server/build.properties
  11. 2
    0
      org.eclipse.jgit.http.server/plugin.properties
  12. 101
    0
      org.eclipse.jgit.http.server/pom.xml
  13. 93
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/AsIsFileFilter.java
  14. 225
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
  15. 236
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitServlet.java
  16. 81
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java
  17. 106
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java
  18. 88
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java
  19. 82
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/NoCacheFilter.java
  20. 175
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java
  21. 150
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java
  22. 216
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java
  23. 85
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java
  24. 74
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ErrorServlet.java
  25. 210
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaServlet.java
  26. 97
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java
  27. 158
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexPipeline.java
  28. 63
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinder.java
  29. 92
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinderImpl.java
  30. 108
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/SuffixPipeline.java
  31. 264
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/UrlPipeline.java
  32. 87
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java
  33. 126
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java
  34. 164
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/FileResolver.java
  35. 77
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/RepositoryResolver.java
  36. 54
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/ServiceNotAuthorizedException.java
  37. 54
    0
      org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/ServiceNotEnabledException.java
  38. 30
    2
      org.eclipse.jgit/src/org/eclipse/jgit/errors/RepositoryNotFoundException.java
  39. 5
    14
      org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
  40. 58
    0
      org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
  41. 39
    0
      org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
  42. 11
    1
      pom.xml

+ 7
- 0
org.eclipse.jgit.http.server/.classpath View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>

+ 125
- 0
org.eclipse.jgit.http.server/.fbprefs View File

@@ -0,0 +1,125 @@
#FindBugs User Preferences
#Mon May 04 16:24:13 PDT 2009
detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true
detectorBadAppletConstructor=BadAppletConstructor|false
detectorBadResultSetAccess=BadResultSetAccess|true
detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true
detectorBadUseOfReturnValue=BadUseOfReturnValue|true
detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true
detectorBooleanReturnNull=BooleanReturnNull|true
detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true
detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true
detectorCheckTypeQualifiers=CheckTypeQualifiers|true
detectorCloneIdiom=CloneIdiom|false
detectorComparatorIdiom=ComparatorIdiom|true
detectorConfusedInheritance=ConfusedInheritance|true
detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true
detectorCrossSiteScripting=CrossSiteScripting|true
detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true
detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true
detectorDontUseEnum=DontUseEnum|true
detectorDroppedException=DroppedException|true
detectorDumbMethodInvocations=DumbMethodInvocations|true
detectorDumbMethods=DumbMethods|true
detectorDuplicateBranches=DuplicateBranches|true
detectorEmptyZipFileEntry=EmptyZipFileEntry|true
detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true
detectorFinalizerNullsFields=FinalizerNullsFields|true
detectorFindBadCast2=FindBadCast2|true
detectorFindBadForLoop=FindBadForLoop|true
detectorFindCircularDependencies=FindCircularDependencies|false
detectorFindDeadLocalStores=FindDeadLocalStores|true
detectorFindDoubleCheck=FindDoubleCheck|true
detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true
detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true
detectorFindFinalizeInvocations=FindFinalizeInvocations|true
detectorFindFloatEquality=FindFloatEquality|true
detectorFindHEmismatch=FindHEmismatch|true
detectorFindInconsistentSync2=FindInconsistentSync2|true
detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true
detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true
detectorFindMaskedFields=FindMaskedFields|true
detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true
detectorFindNakedNotify=FindNakedNotify|true
detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|true
detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true
detectorFindNonShortCircuit=FindNonShortCircuit|true
detectorFindNullDeref=FindNullDeref|true
detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true
detectorFindOpenStream=FindOpenStream|true
detectorFindPuzzlers=FindPuzzlers|true
detectorFindRefComparison=FindRefComparison|true
detectorFindReturnRef=FindReturnRef|true
detectorFindRunInvocations=FindRunInvocations|true
detectorFindSelfComparison=FindSelfComparison|true
detectorFindSelfComparison2=FindSelfComparison2|true
detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true
detectorFindSpinLoop=FindSpinLoop|true
detectorFindSqlInjection=FindSqlInjection|true
detectorFindTwoLockWait=FindTwoLockWait|true
detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true
detectorFindUnconditionalWait=FindUnconditionalWait|true
detectorFindUninitializedGet=FindUninitializedGet|true
detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true
detectorFindUnreleasedLock=FindUnreleasedLock|true
detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true
detectorFindUnsyncGet=FindUnsyncGet|true
detectorFindUselessControlFlow=FindUselessControlFlow|true
detectorFormatStringChecker=FormatStringChecker|true
detectorHugeSharedStringConstants=HugeSharedStringConstants|true
detectorIDivResultCastToDouble=IDivResultCastToDouble|true
detectorIncompatMask=IncompatMask|true
detectorInconsistentAnnotations=InconsistentAnnotations|true
detectorInefficientMemberAccess=InefficientMemberAccess|false
detectorInefficientToArray=InefficientToArray|true
detectorInfiniteLoop=InfiniteLoop|true
detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true
detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false
detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true
detectorInitializationChain=InitializationChain|true
detectorInstantiateStaticClass=InstantiateStaticClass|true
detectorInvalidJUnitTest=InvalidJUnitTest|true
detectorIteratorIdioms=IteratorIdioms|true
detectorLazyInit=LazyInit|true
detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true
detectorMethodReturnCheck=MethodReturnCheck|true
detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true
detectorMutableLock=MutableLock|true
detectorMutableStaticFields=MutableStaticFields|true
detectorNaming=Naming|true
detectorNumberConstructor=NumberConstructor|true
detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true
detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true
detectorPublicSemaphores=PublicSemaphores|false
detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true
detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true
detectorRedundantInterfaces=RedundantInterfaces|true
detectorRepeatedConditionals=RepeatedConditionals|true
detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true
detectorSerializableIdiom=SerializableIdiom|true
detectorStartInConstructor=StartInConstructor|true
detectorStaticCalendarDetector=StaticCalendarDetector|true
detectorStringConcatenation=StringConcatenation|true
detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true
detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true
detectorSwitchFallthrough=SwitchFallthrough|true
detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true
detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true
detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true
detectorURLProblems=URLProblems|true
detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true
detectorUnnecessaryMath=UnnecessaryMath|true
detectorUnreadFields=UnreadFields|true
detectorUseObjectEquals=UseObjectEquals|false
detectorUselessSubclassMethod=UselessSubclassMethod|false
detectorVarArgsProblems=VarArgsProblems|true
detectorVolatileUsage=VolatileUsage|true
detectorWaitInLoop=WaitInLoop|true
detectorWrongMapIterator=WrongMapIterator|true
detectorXMLFactoryBypass=XMLFactoryBypass|true
detector_threshold=2
effort=default
excludefilter0=findBugs/FindBugsExcludeFilter.xml
filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,MT_CORRECTNESS,PERFORMANCE,STYLE|false
filter_settings_neg=MALICIOUS_CODE,NOISE,I18N,SECURITY,EXPERIMENTAL|
run_at_full_build=true

+ 2
- 0
org.eclipse.jgit.http.server/.gitignore View File

@@ -0,0 +1,2 @@
/bin
/target

+ 28
- 0
org.eclipse.jgit.http.server/.project View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.jgit.http.server</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
</natures>
</projectDescription>

+ 3
- 0
org.eclipse.jgit.http.server/.settings/org.eclipse.core.resources.prefs View File

@@ -0,0 +1,3 @@
#Mon Aug 11 16:46:12 PDT 2008
eclipse.preferences.version=1
encoding/<project>=UTF-8

+ 3
- 0
org.eclipse.jgit.http.server/.settings/org.eclipse.core.runtime.prefs View File

@@ -0,0 +1,3 @@
#Mon Mar 24 18:55:50 EDT 2008
eclipse.preferences.version=1
line.separator=\n

+ 334
- 0
org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs View File

@@ -0,0 +1,334 @@
#Fri Oct 02 18:43:47 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=error
org.eclipse.jdt.core.compiler.problem.unusedLabel=error
org.eclipse.jdt.core.compiler.problem.unusedLocal=error
org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=1
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=80
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

+ 61
- 0
org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.ui.prefs View File

@@ -0,0 +1,61 @@
#Wed Jan 06 12:13:14 PST 2010
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_JGit Format
formatter_settings_version=11
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=java;javax;org;com;
org.eclipse.jdt.ui.ondemandthreshold=99
org.eclipse.jdt.ui.staticondemandthreshold=99
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=false
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=false
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_trailing_whitespaces=true
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=false
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

+ 21
- 0
org.eclipse.jgit.http.server/META-INF/MANIFEST.MF View File

@@ -0,0 +1,21 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %plugin_name
Bundle-SymbolicName: org.eclipse.jgit.http.server
Bundle-Version: 0.6.0.qualifier
Bundle-Localization: plugin
Bundle-Vendor: %provider_name
Export-Package:
org.eclipse.jgit.http.server;version="0.6.0",
org.eclipse.jgit.http.server.glue;version="0.6.0",
org.eclipse.jgit.http.server.resolver;version="0.6.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
javax.servlet.http;version="[2.5.0,3.0.0)",
org.eclipse.jgit.errors;version="0.6.0",
org.eclipse.jgit.lib;version="0.6.0",
org.eclipse.jgit.revwalk;version="0.6.0",
org.eclipse.jgit.transport;version="0.6.0",
org.eclipse.jgit.util;version="0.6.0",
org.eclipse.jgit.util.io;version="0.6.0"

+ 5
- 0
org.eclipse.jgit.http.server/build.properties View File

@@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.properties

+ 2
- 0
org.eclipse.jgit.http.server/plugin.properties View File

@@ -0,0 +1,2 @@
plugin_name=Java Git HTTP Server (Incubation)
provider_name=eclipse.org

+ 101
- 0
org.eclipse.jgit.http.server/pom.xml View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009-2010, Google Inc.
Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com>
and other copyright owners as documented in the project's IP log.

This program and the accompanying materials are made available
under the terms of the Eclipse Distribution License v1.0 which
accompanies this distribution, is reproduced below, and is
available at http://www.eclipse.org/org/documents/edl-v10.php

All rights reserved.

Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.

- Neither the name of the Eclipse Foundation, Inc. nor the
names of its contributors may be used to endorse or promote
products derived from this software without specific prior
written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
<version>0.6.0-SNAPSHOT</version>
</parent>

<artifactId>org.eclipse.jgit.http.server</artifactId>
<name>JGit - HTTP Server</name>

<description>
Git aware HTTP server implementation.
</description>

<dependencies>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<sourceDirectory>src/</sourceDirectory>

<resources>
<resource>
<directory>.</directory>
<includes>
<include>plugin.properties</include>
</includes>
</resource>
</resources>

<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

+ 93
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/AsIsFileFilter.java View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.http.server.resolver.AsIsFileService;
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.lib.Repository;

class AsIsFileFilter implements Filter {
private final AsIsFileService asIs;

AsIsFileFilter(final AsIsFileService getAnyFile) {
this.asIs = getAnyFile;
}

public void init(FilterConfig config) throws ServletException {
// Do nothing.
}

public void destroy() {
// Do nothing.
}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
final Repository db = getRepository(request);
asIs.access((HttpServletRequest) request, db);
chain.doFilter(request, response);
} catch (ServiceNotAuthorizedException e) {
((HttpServletResponse) response).sendError(SC_UNAUTHORIZED);
} catch (ServiceNotEnabledException e) {
((HttpServletResponse) response).sendError(SC_FORBIDDEN);
}
}
}

+ 225
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java View File

@@ -0,0 +1,225 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE;
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_RANGES;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_RANGE;
import static org.eclipse.jgit.util.HttpSupport.HDR_IF_RANGE;
import static org.eclipse.jgit.util.HttpSupport.HDR_RANGE;

import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.util.IO;

/**
* Dumps a file over HTTP GET (or its information via HEAD).
* <p>
* Supports a single byte range requested via {@code Range} HTTP header. This
* feature supports a dumb client to resume download of a larger object file.
*/
final class FileSender {
private final File path;

private final RandomAccessFile source;

private final long lastModified;

private final long fileLen;

private long pos;

private long end;

FileSender(final File path) throws FileNotFoundException {
this.path = path;
this.source = new RandomAccessFile(path, "r");

try {
this.lastModified = path.lastModified();
this.fileLen = source.getChannel().size();
this.end = fileLen;
} catch (IOException e) {
try {
source.close();
} catch (IOException closeError) {
// Ignore any error closing the stream.
}

final FileNotFoundException r;
r = new FileNotFoundException("Cannot get length of " + path);
r.initCause(e);
throw r;
}
}

void close() {
try {
source.close();
} catch (IOException e) {
// Ignore close errors on a read-only stream.
}
}

long getLastModified() {
return lastModified;
}

String getTailChecksum() throws IOException {
final int n = 20;
final byte[] buf = new byte[n];
IO.readFully(source.getChannel(), fileLen - n, buf, 0, n);
return ObjectId.fromRaw(buf).getName();
}

void serve(final HttpServletRequest req, final HttpServletResponse rsp,
final boolean sendBody) throws IOException {
if (!initRangeRequest(req, rsp)) {
rsp.sendError(SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return;
}

rsp.setHeader(HDR_ACCEPT_RANGES, "bytes");
rsp.setHeader(HDR_CONTENT_LENGTH, Long.toString(end - pos));

if (sendBody) {
final OutputStream out = rsp.getOutputStream();
try {
final byte[] buf = new byte[4096];
while (pos < end) {
final int r = (int) Math.min(buf.length, end - pos);
final int n = source.read(buf, 0, r);
if (n < 0) {
throw new EOFException("Unexpected EOF on " + path);
}
out.write(buf, 0, n);
pos += n;
}
out.flush();
} finally {
out.close();
}
}
}

private boolean initRangeRequest(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
final Enumeration<String> rangeHeaders = getRange(req);
if (!rangeHeaders.hasMoreElements()) {
// No range headers, the request is fine.
return true;
}

final String range = rangeHeaders.nextElement();
if (rangeHeaders.hasMoreElements()) {
// To simplify the code we support only one range.
return false;
}

final int eq = range.indexOf('=');
final int dash = range.indexOf('-');
if (eq < 0 || dash < 0 || !range.startsWith("bytes=")) {
return false;
}

final String ifRange = req.getHeader(HDR_IF_RANGE);
if (ifRange != null && !getTailChecksum().equals(ifRange)) {
// If the client asked us to verify the ETag and its not
// what they expected we need to send the entire content.
return true;
}

try {
if (eq + 1 == dash) {
// "bytes=-500" means last 500 bytes
pos = Long.parseLong(range.substring(dash + 1));
pos = fileLen - pos;
} else {
// "bytes=500-" (position 500 to end)
// "bytes=500-1000" (position 500 to 1000)
pos = Long.parseLong(range.substring(eq + 1, dash));
if (dash < range.length() - 1) {
end = Long.parseLong(range.substring(dash + 1));
end++; // range was inclusive, want exclusive
}
}
} catch (NumberFormatException e) {
// We probably hit here because of a non-digit such as
// "," appearing at the end of the first range telling
// us there is a second range following. To simplify
// the code we support only one range.
return false;
}

if (end > fileLen) {
end = fileLen;
}
if (pos >= end) {
return false;
}

rsp.setStatus(SC_PARTIAL_CONTENT);
rsp.setHeader(HDR_CONTENT_RANGE, "bytes " + pos + "-" + (end - 1) + "/"
+ fileLen);
source.seek(pos);
return true;
}

@SuppressWarnings("unchecked")
private static Enumeration<String> getRange(final HttpServletRequest req) {
return req.getHeaders(HDR_RANGE);
}
}

+ 236
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitServlet.java View File

@@ -0,0 +1,236 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import java.io.File;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

import org.eclipse.jgit.http.server.glue.MetaServlet;
import org.eclipse.jgit.http.server.glue.RegexGroupFilter;
import org.eclipse.jgit.http.server.glue.ServletBinder;
import org.eclipse.jgit.http.server.resolver.FileResolver;
import org.eclipse.jgit.http.server.resolver.AsIsFileService;
import org.eclipse.jgit.http.server.resolver.RepositoryResolver;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.StringUtils;

/**
* Handles Git repository access over HTTP.
* <p>
* Applications embedding this servlet should map a directory path within the
* application to this servlet, for example:
*
* <pre>
* &lt;servlet&gt;
* &lt;servlet-name&gt;GitServlet&lt;/servlet-name&gt;
* &lt;servlet-class&gt;org.eclipse.jgit.http.server.GitServlet&lt;/servlet-class&gt;
* &lt;init-param&gt;
* &lt;param-name&gt;base-path&lt;/param-name&gt;
* &lt;param-value&gt;/var/srv/git&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;init-param&gt;
* &lt;param-name&gt;export-all&lt;/param-name&gt;
* &lt;param-value&gt;0&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;/servlet&gt;
* &lt;servlet-mapping&gt;
* &lt;servlet-name&gt;GitServlet&lt;/servlet-name&gt;
* &lt;url-pattern&gt;/git/*&lt;/url-pattern&gt;
* &lt;/servlet-mapping&gt;
* </pre>
*
* <p>
* Applications may wish to add additional repository action URLs to this
* servlet by taking advantage of its extension from {@link MetaServlet}.
* Callers may register their own URL suffix translations through
* {@link #serve(String)}, or their regex translations through
* {@link #serveRegex(String)}. Each translation should contain a complete
* filter pipeline which ends with the HttpServlet that should handle the
* requested action.
*/
public class GitServlet extends MetaServlet {
private static final long serialVersionUID = 1L;

private volatile boolean initialized;

private RepositoryResolver resolver;

private AsIsFileService asIs = new AsIsFileService();

/**
* New servlet that will load its base directory from {@code web.xml}.
* <p>
* The required parameter {@code base-path} must be configured to point to
* the local filesystem directory where all served Git repositories reside.
*/
public GitServlet() {
// Initialized above by field declarations.
}

/**
* New servlet configured with a specific resolver.
*
* @param resolver
* the resolver to use when matching URL to Git repository. If
* null the {@code base-path} parameter will be looked for in the
* parameter table during init, which usually comes from the
* {@code web.xml} file of the web application.
*/
public void setRepositoryResolver(RepositoryResolver resolver) {
assertNotInitialized();
this.resolver = resolver;
}

/**
* @param f
* the filter to validate direct access to repository files
* through a dumb client. If {@code null} then dumb client
* support is completely disabled.
*/
public void setAsIsFileService(AsIsFileService f) {
assertNotInitialized();
this.asIs = f != null ? f : AsIsFileService.DISABLED;
}

private void assertNotInitialized() {
if (initialized)
throw new IllegalStateException("Already initialized by container");
}

@Override
public void init(final ServletConfig config) throws ServletException {
super.init(config);

if (resolver == null) {
final File root = getFile("base-path");
final boolean exportAll = getBoolean("export-all");
setRepositoryResolver(new FileResolver(root, exportAll));
}

initialized = true;

if (asIs != AsIsFileService.DISABLED) {
final IsLocalFilter mustBeLocal = new IsLocalFilter();
final AsIsFileFilter enabled = new AsIsFileFilter(asIs);

serve("*/" + Constants.INFO_REFS)//
.through(mustBeLocal)//
.through(enabled)//
.with(new InfoRefsServlet());

serve("*/" + Constants.HEAD)//
.through(mustBeLocal)//
.through(enabled)//
.with(new TextFileServlet(Constants.HEAD));

final String info_alternates = "objects/info/alternates";
serve("*/" + info_alternates)//
.through(mustBeLocal)//
.through(enabled)//
.with(new TextFileServlet(info_alternates));

final String http_alternates = "objects/info/http-alternates";
serve("*/" + http_alternates)//
.through(mustBeLocal)//
.through(enabled)//
.with(new TextFileServlet(http_alternates));

serve("*/objects/info/packs")//
.through(mustBeLocal)//
.through(enabled)//
.with(new InfoPacksServlet());

serveRegex("^/(.*)/objects/([0-9a-f]{2}/[0-9a-f]{38})$")//
.through(mustBeLocal)//
.through(enabled)//
.through(new RegexGroupFilter(2))//
.with(new ObjectFileServlet.Loose());

serveRegex("^/(.*)/objects/(pack/pack-[0-9a-f]{40}\\.pack)$")//
.through(mustBeLocal)//
.through(enabled)//
.through(new RegexGroupFilter(2))//
.with(new ObjectFileServlet.Pack());

serveRegex("^/(.*)/objects/(pack/pack-[0-9a-f]{40}\\.idx)$")//
.through(mustBeLocal)//
.through(enabled)//
.through(new RegexGroupFilter(2))//
.with(new ObjectFileServlet.PackIdx());
}
}

private File getFile(final String param) throws ServletException {
String n = getInitParameter(param);
if (n == null || "".equals(n))
throw new ServletException("Parameter " + param + " not set");

File path = new File(n);
if (!path.exists())
throw new ServletException(path + " (for " + param + ") not found");
return path;
}

private boolean getBoolean(String param) throws ServletException {
String n = getInitParameter(param);
if (n == null)
return false;
try {
return StringUtils.toBoolean(n);
} catch (IllegalArgumentException err) {
throw new ServletException("Invalid boolean " + param + " = " + n);
}
}

@Override
protected ServletBinder register(ServletBinder binder) {
if (resolver == null)
throw new IllegalStateException("No resolver available");
binder = binder.through(new NoCacheFilter());
binder = binder.through(new RepositoryFilter(resolver));
return binder;
}
}

+ 81
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import static org.eclipse.jgit.http.server.ServletUtils.sendPlainText;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.ObjectDatabase;
import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.PackFile;

/** Sends the current list of pack files, sorted most recent first. */
class InfoPacksServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

public void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
sendPlainText(packList(req), req, rsp);
}

private static String packList(final HttpServletRequest req) {
final StringBuilder out = new StringBuilder();
final ObjectDatabase db = getRepository(req).getObjectDatabase();
if (db instanceof ObjectDirectory) {
for (PackFile pack : ((ObjectDirectory) db).getPacks()) {
out.append("P ");
out.append(pack.getPackFile().getName());
out.append('\n');
}
}
out.append('\n');
return out.toString();
}
}

+ 106
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import static org.eclipse.jgit.http.server.ServletUtils.send;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RefAdvertiser;
import org.eclipse.jgit.util.HttpSupport;

/** Send a complete list of current refs, including peeled values for tags. */
class InfoRefsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

public void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
// Assume a dumb client and send back the dumb client
// version of the info/refs file.
final byte[] raw = dumbHttp(req);
rsp.setContentType(HttpSupport.TEXT_PLAIN);
rsp.setCharacterEncoding(Constants.CHARACTER_ENCODING);
send(raw, req, rsp);
}

private byte[] dumbHttp(final HttpServletRequest req) throws IOException {
final Repository db = getRepository(req);
final RevWalk walk = new RevWalk(db);
final RevFlag ADVERTISED = walk.newFlag("ADVERTISED");
final StringBuilder out = new StringBuilder();
final RefAdvertiser adv = new RefAdvertiser() {
@Override
protected void writeOne(final CharSequence line) {
// Whoever decided that info/refs should use a different
// delimiter than the native git:// protocol shouldn't
// be allowed to design this sort of stuff. :-(
out.append(line.toString().replace(' ', '\t'));
}

@Override
protected void end() {
// No end marker required for info/refs format.
}
};
adv.init(walk, ADVERTISED);
adv.setDerefTags(true);

Map<String, Ref> refs = new HashMap<String, Ref>(db.getAllRefs());
refs.remove(Constants.HEAD);
adv.send(refs.values());
return out.toString().getBytes(Constants.CHARACTER_ENCODING);
}
}

+ 88
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.Repository;

/**
* Requires the target {@link Repository} to be available via local filesystem.
* <p>
* The target {@link Repository} must be using a {@link ObjectDirectory}, so the
* downstream servlet can directly access its contents on disk.
*/
class IsLocalFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
// Do nothing.
}

public void destroy() {
// Do nothing.
}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (isLocal(getRepository(request)))
chain.doFilter(request, response);
else
((HttpServletResponse) response).sendError(SC_FORBIDDEN);
}

private static boolean isLocal(final Repository db) {
return db.getObjectDatabase() instanceof ObjectDirectory;
}
}

+ 82
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/NoCacheFilter.java View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static org.eclipse.jgit.util.HttpSupport.HDR_CACHE_CONTROL;
import static org.eclipse.jgit.util.HttpSupport.HDR_EXPIRES;
import static org.eclipse.jgit.util.HttpSupport.HDR_PRAGMA;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

/** Adds HTTP response headers to prevent caching by proxies/browsers. */
class NoCacheFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
// Do nothing.
}

public void destroy() {
// Do nothing.
}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse rsp = (HttpServletResponse) response;

rsp.setHeader(HDR_EXPIRES, "Fri, 01 Jan 1980 00:00:00 GMT");
rsp.setHeader(HDR_PRAGMA, "no-cache");

final String nocache = "no-cache, max-age=0, must-revalidate";
rsp.setHeader(HDR_CACHE_CONTROL, nocache);

chain.doFilter(request, response);
}
}

+ 175
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import static org.eclipse.jgit.util.HttpSupport.HDR_ETAG;
import static org.eclipse.jgit.util.HttpSupport.HDR_IF_MODIFIED_SINCE;
import static org.eclipse.jgit.util.HttpSupport.HDR_IF_NONE_MATCH;
import static org.eclipse.jgit.util.HttpSupport.HDR_LAST_MODIFIED;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.Repository;

/** Sends any object from {@code GIT_DIR/objects/??/0 38}, or any pack file. */
abstract class ObjectFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

static class Loose extends ObjectFileServlet {
private static final long serialVersionUID = 1L;

Loose() {
super("application/x-git-loose-object");
}

@Override
String etag(final FileSender sender) throws IOException {
return Long.toHexString(sender.getLastModified());
}
}

private static abstract class PackData extends ObjectFileServlet {
private static final long serialVersionUID = 1L;

PackData(String contentType) {
super(contentType);
}

@Override
String etag(final FileSender sender) throws IOException {
return sender.getTailChecksum();
}
}

static class Pack extends PackData {
private static final long serialVersionUID = 1L;

Pack() {
super("application/x-git-packed-objects");
}
}

static class PackIdx extends PackData {
private static final long serialVersionUID = 1L;

PackIdx() {
super("application/x-git-packed-objects-toc");
}
}

private final String contentType;

ObjectFileServlet(final String contentType) {
this.contentType = contentType;
}

abstract String etag(FileSender sender) throws IOException;

@Override
public void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
serve(req, rsp, true);
}

@Override
protected void doHead(final HttpServletRequest req,
final HttpServletResponse rsp) throws ServletException, IOException {
serve(req, rsp, false);
}

private void serve(final HttpServletRequest req,
final HttpServletResponse rsp, final boolean sendBody)
throws IOException {
final File obj = new File(objects(req), req.getPathInfo());
final FileSender sender;
try {
sender = new FileSender(obj);
} catch (FileNotFoundException e) {
rsp.sendError(SC_NOT_FOUND);
return;
}

try {
final String etag = etag(sender);
final long lastModified = (sender.getLastModified() / 1000) * 1000;

String ifNoneMatch = req.getHeader(HDR_IF_NONE_MATCH);
if (etag != null && etag.equals(ifNoneMatch)) {
rsp.sendError(SC_NOT_MODIFIED);
return;
}

long ifModifiedSince = req.getDateHeader(HDR_IF_MODIFIED_SINCE);
if (0 < lastModified && lastModified < ifModifiedSince) {
rsp.sendError(SC_NOT_MODIFIED);
return;
}

if (etag != null)
rsp.setHeader(HDR_ETAG, etag);
if (0 < lastModified)
rsp.setDateHeader(HDR_LAST_MODIFIED, lastModified);
rsp.setContentType(contentType);
sender.serve(req, rsp, sendBody);
} finally {
sender.close();
}
}

private static File objects(final HttpServletRequest req) {
final Repository db = getRepository(req);
return ((ObjectDirectory) db.getObjectDatabase()).getDirectory();
}
}

+ 150
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java View File

@@ -0,0 +1,150 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_REPOSITORY;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.http.server.resolver.RepositoryResolver;
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.lib.Repository;

/**
* Opens a repository named by the path info through {@link RepositoryResolver}.
* <p>
* This filter assumes it is invoked by {@link GitServlet} and is likely to not
* work as expected if called from any other class. This filter assumes the path
* info of the current request is a repository name which can be used by the
* configured {@link RepositoryResolver} to open a {@link Repository} and attach
* it to the current request.
* <p>
* This filter sets request attribute {@link ServletUtils#ATTRIBUTE_REPOSITORY}
* when it discovers the repository, and automatically closes and removes the
* attribute when the request is complete.
*/
public class RepositoryFilter implements Filter {
private final RepositoryResolver resolver;

private ServletContext context;

/**
* Create a new filter.
*
* @param resolver
* the resolver which will be used to translate the URL name
* component to the actual {@link Repository} instance for the
* current web request.
*/
public RepositoryFilter(final RepositoryResolver resolver) {
this.resolver = resolver;
}

public void init(final FilterConfig config) throws ServletException {
context = config.getServletContext();
}

public void destroy() {
context = null;
}

public void doFilter(final ServletRequest request,
final ServletResponse rsp, final FilterChain chain)
throws IOException, ServletException {
if (request.getAttribute(ATTRIBUTE_REPOSITORY) != null) {
context.log("Internal server error, request attribute "
+ ATTRIBUTE_REPOSITORY + " was already set when "
+ getClass().getName() + " was invoked.");
((HttpServletResponse) rsp).sendError(SC_INTERNAL_SERVER_ERROR);
return;
}

final HttpServletRequest req = (HttpServletRequest) request;

String name = req.getPathInfo();
if (name == null || name.length() == 0) {
((HttpServletResponse) rsp).sendError(SC_NOT_FOUND);
return;
}
if (name.startsWith("/"))
name = name.substring(1);

final Repository db;
try {
db = resolver.open(req, name);
} catch (RepositoryNotFoundException e) {
((HttpServletResponse) rsp).sendError(SC_NOT_FOUND);
return;
} catch (ServiceNotAuthorizedException e) {
((HttpServletResponse) rsp).sendError(SC_UNAUTHORIZED);
return;
} catch (ServiceNotEnabledException e) {
((HttpServletResponse) rsp).sendError(SC_FORBIDDEN);
return;
}
try {
request.setAttribute(ATTRIBUTE_REPOSITORY, db);
chain.doFilter(request, rsp);
} finally {
request.removeAttribute(ATTRIBUTE_REPOSITORY);
db.close();
}
}
}

+ 216
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java View File

@@ -0,0 +1,216 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static org.eclipse.jgit.util.HttpSupport.ENCODING_GZIP;
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_ENCODING;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING;
import static org.eclipse.jgit.util.HttpSupport.HDR_ETAG;
import static org.eclipse.jgit.util.HttpSupport.TEXT_PLAIN;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;

/** Common utility functions for servlets. */
public final class ServletUtils {
/** Request attribute which stores the {@link Repository} instance. */
public static final String ATTRIBUTE_REPOSITORY = "org.eclipse.jgit.Repository";

/**
* Get the selected repository from the request.
*
* @param req
* the current request.
* @return the repository; never null.
* @throws IllegalStateException
* the repository was not set by the filter, the servlet is
* being invoked incorrectly and the programmer should ensure
* the filter runs before the servlet.
* @see #ATTRIBUTE_REPOSITORY
*/
public static Repository getRepository(final ServletRequest req) {
Repository db = (Repository) req.getAttribute(ATTRIBUTE_REPOSITORY);
if (db == null)
throw new IllegalStateException("Expected Repository attribute");
return db;
}

/**
* Open the request input stream, automatically inflating if necessary.
* <p>
* This method automatically inflates the input stream if the request
* {@code Content-Encoding} header was set to {@code gzip} or the legacy
* {@code x-gzip}.
*
* @param req
* the incoming request whose input stream needs to be opened.
* @return an input stream to read the raw, uncompressed request body.
* @throws IOException
* if an input or output exception occurred.
*/
public static InputStream getInputStream(final HttpServletRequest req)
throws IOException {
InputStream in = req.getInputStream();
final String enc = req.getHeader(HDR_CONTENT_ENCODING);
if (ENCODING_GZIP.equals(enc) || "x-gzip".equals(enc)) //$NON-NLS-1$
in = new GZIPInputStream(in);
else if (enc != null)
throw new IOException(HDR_CONTENT_ENCODING + " \"" + enc + "\""
+ ": not supported by this library.");
return in;
}

/**
* Send a plain text response to a {@code GET} or {@code HEAD} HTTP request.
* <p>
* The text response is encoded in the Git character encoding, UTF-8.
* <p>
* If the user agent supports a compressed transfer encoding and the content
* is large enough, the content may be compressed before sending.
* <p>
* The {@code ETag} and {@code Content-Length} headers are automatically set
* by this method. {@code Content-Encoding} is conditionally set if the user
* agent supports a compressed transfer. Callers are responsible for setting
* any cache control headers.
*
* @param content
* to return to the user agent as this entity's body.
* @param req
* the incoming request.
* @param rsp
* the outgoing response.
* @throws IOException
* the servlet API rejected sending the body.
*/
public static void sendPlainText(final String content,
final HttpServletRequest req, final HttpServletResponse rsp)
throws IOException {
final byte[] raw = content.getBytes(Constants.CHARACTER_ENCODING);
rsp.setContentType(TEXT_PLAIN);
rsp.setCharacterEncoding(Constants.CHARACTER_ENCODING);
send(raw, req, rsp);
}

/**
* Send a response to a {@code GET} or {@code HEAD} HTTP request.
* <p>
* If the user agent supports a compressed transfer encoding and the content
* is large enough, the content may be compressed before sending.
* <p>
* The {@code ETag} and {@code Content-Length} headers are automatically set
* by this method. {@code Content-Encoding} is conditionally set if the user
* agent supports a compressed transfer. Callers are responsible for setting
* {@code Content-Type} and any cache control headers.
*
* @param content
* to return to the user agent as this entity's body.
* @param req
* the incoming request.
* @param rsp
* the outgoing response.
* @throws IOException
* the servlet API rejected sending the body.
*/
public static void send(byte[] content, final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
content = sendInit(content, req, rsp);
final OutputStream out = rsp.getOutputStream();
try {
out.write(content);
out.flush();
} finally {
out.close();
}
}

private static byte[] sendInit(byte[] content,
final HttpServletRequest req, final HttpServletResponse rsp)
throws IOException {
rsp.setHeader(HDR_ETAG, etag(content));
if (256 < content.length && acceptsGzipEncoding(req)) {
content = compress(content);
rsp.setHeader(HDR_CONTENT_ENCODING, ENCODING_GZIP);
}
rsp.setContentLength(content.length);
return content;
}

private static boolean acceptsGzipEncoding(final HttpServletRequest req) {
final String accepts = req.getHeader(HDR_ACCEPT_ENCODING);
return accepts != null && 0 <= accepts.indexOf(ENCODING_GZIP);
}

private static byte[] compress(final byte[] raw) throws IOException {
final int maxLen = raw.length + 32;
final ByteArrayOutputStream out = new ByteArrayOutputStream(maxLen);
final GZIPOutputStream gz = new GZIPOutputStream(out);
gz.write(raw);
gz.finish();
gz.flush();
return out.toByteArray();
}

private static String etag(final byte[] content) {
final MessageDigest md = Constants.newMessageDigest();
md.update(content);
return ObjectId.fromRaw(md.digest()).getName();
}

private ServletUtils() {
// static utility class only
}
}

+ 85
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server;

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import static org.eclipse.jgit.http.server.ServletUtils.send;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.util.HttpSupport;
import org.eclipse.jgit.util.IO;

/** Sends a small text meta file from the repository. */
class TextFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private final String fileName;

TextFileServlet(final String name) {
this.fileName = name;
}

public void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
try {
rsp.setContentType(HttpSupport.TEXT_PLAIN);
send(read(req), req, rsp);
} catch (FileNotFoundException noFile) {
rsp.sendError(SC_NOT_FOUND);
}
}

private byte[] read(final HttpServletRequest req) throws IOException {
final File gitdir = getRepository(req).getDirectory();
return IO.readFully(new File(gitdir, fileName));
}
}

+ 74
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ErrorServlet.java View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/** Sends a fixed status code to the client. */
public class ErrorServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private final int status;

/**
* Sends a specific status code.
*
* @param status
* the HTTP status code to always send.
*/
public ErrorServlet(final int status) {
this.status = status;
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse rsp)
throws ServletException, IOException {
rsp.sendError(status);
}
}

+ 210
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaServlet.java View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;

import java.io.IOException;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Generic container servlet to manage routing to different pipelines.
* <p>
* Callers can create and configure a new processing pipeline by using one of
* the {@link #serve(String)} or {@link #serveRegex(String)} methods to allocate
* a binder for a particular URL pattern.
* <p>
* Registered filters and servlets are initialized lazily, usually during the
* first request. Once initialized the bindings in this servlet cannot be
* modified without destroying the servlet and thereby destroying all registered
* filters and servlets.
*/
public class MetaServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

static final String REGEX_GROUPS = "org.eclipse.jgit.http.server.glue.MetaServlet.serveRegex";

private final List<ServletBinderImpl> bindings;

private volatile UrlPipeline[] pipelines;

/** Empty servlet with no bindings. */
public MetaServlet() {
this.bindings = new ArrayList<ServletBinderImpl>();
}

/**
* Construct a binding for a specific path.
*
* @param path
* pattern to match.
* @return binder for the passed path.
*/
public ServletBinder serve(String path) {
if (path.startsWith("*"))
return register(new SuffixPipeline.Binder(path.substring(1)));
throw new IllegalArgumentException("\"" + path + "\" not supported");
}

/**
* Construct a binding for a regular expression.
*
* @param expression
* the regular expression to pattern match the URL against.
* @return binder for the passed expression.
*/
public ServletBinder serveRegex(String expression) {
return register(new RegexPipeline.Binder(expression));
}

public void destroy() {
if (pipelines != null) {
Set<Object> destroyed = newIdentitySet();
for (UrlPipeline p : pipelines)
p.destroy(destroyed);
pipelines = null;
}
}

private static Set<Object> newIdentitySet() {
final Map<Object, Object> m = new IdentityHashMap<Object, Object>();
return new AbstractSet<Object>() {
@Override
public boolean add(Object o) {
return m.put(o, o) == null;
}

@Override
public boolean contains(Object o) {
return m.keySet().contains(o);
}

@Override
public Iterator<Object> iterator() {
return m.keySet().iterator();
}

@Override
public int size() {
return m.size();
}
};
}

@Override
protected void service(final HttpServletRequest req,
final HttpServletResponse rsp) throws ServletException, IOException {
final UrlPipeline p = find(req);
if (p != null)
p.service(req, rsp);
else
rsp.sendError(SC_NOT_FOUND);
}

private UrlPipeline find(final HttpServletRequest req)
throws ServletException {
for (UrlPipeline p : getPipelines())
if (p.match(req))
return p;
return null;
}

private ServletBinder register(ServletBinderImpl b) {
synchronized (bindings) {
if (pipelines != null)
throw new IllegalStateException("Servlet already initialized");
bindings.add(b);
}
return register((ServletBinder) b);
}

/**
* Configure a newly created binder.
*
* @param b
* the newly created binder.
* @return binder for the caller, potentially after adding one or more
* filters into the pipeline.
*/
protected ServletBinder register(ServletBinder b) {
return b;
}

private UrlPipeline[] getPipelines() throws ServletException {
UrlPipeline[] r = pipelines;
if (r == null) {
synchronized (bindings) {
r = pipelines;
if (r == null) {
r = createPipelines();
pipelines = r;
}
}
}
return r;
}

private UrlPipeline[] createPipelines() throws ServletException {
UrlPipeline[] array = new UrlPipeline[bindings.size()];

for (int i = 0; i < bindings.size(); i++)
array[i] = bindings.get(i).create();

Set<Object> inited = newIdentitySet();
for (UrlPipeline p : array)
p.init(getServletContext(), inited);
return array;
}
}

+ 97
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
* Switch servlet path and path info to use another regex match group.
* <p>
* This filter is meant to be installed in the middle of a pipeline created by
* {@link MetaServlet#serveRegex(String)}. The passed request's servlet path is
* updated to be all text up to the start of the designated capture group, and
* the path info is changed to the contents of the capture group.
**/
public class RegexGroupFilter implements Filter {
private final int groupIdx;

/**
* @param groupIdx
* capture group number, 1 through the number of groups.
*/
public RegexGroupFilter(final int groupIdx) {
if (groupIdx < 1)
throw new IllegalArgumentException("Invalid index: " + groupIdx);
this.groupIdx = groupIdx - 1;
}

public void init(FilterConfig config) throws ServletException {
// Do nothing.
}

public void destroy() {
// Do nothing.
}

public void doFilter(final ServletRequest request,
final ServletResponse rsp, final FilterChain chain)
throws IOException, ServletException {
final WrappedRequest[] g = groupsFor(request);
if (groupIdx < g.length)
chain.doFilter(g[groupIdx], rsp);
else
throw new ServletException("Invalid regex group " + (groupIdx + 1));
}

private static WrappedRequest[] groupsFor(final ServletRequest r) {
return (WrappedRequest[]) r.getAttribute(MetaServlet.REGEX_GROUPS);
}
}

+ 158
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexPipeline.java View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static org.eclipse.jgit.http.server.glue.MetaServlet.REGEX_GROUPS;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Selects requests by matching the URI against a regular expression.
* <p>
* The pattern is bound and matched against the path info of the servlet
* request, as this class assumes it is invoked by {@link MetaServlet}.
* <p>
* If there are capture groups in the regular expression, the matched ranges of
* the capture groups are stored as an array of modified HttpServetRequests,
* into the request attribute {@link MetaServlet#REGEX_GROUPS}.
* <p>
* Each servlet request has been altered to have its {@code getPathInfo()}
* method return the matched text of the corresponding capture group. A
* {@link RegexGroupFilter} can be applied in the pipeline to switch the current
* HttpServletRequest to reference a different capture group before running
* additional filters, or the final servlet.
* <p>
* This class dispatches the remainder of the pipeline using the first capture
* group as the current request, making {@code RegexGroupFilter} required only
* to access capture groups beyond the first.
*/
class RegexPipeline extends UrlPipeline {
static class Binder extends ServletBinderImpl {
private final Pattern pattern;

Binder(final String p) {
pattern = Pattern.compile(p);
}

UrlPipeline create() {
return new RegexPipeline(pattern, getFilters(), getServlet());
}
}

private final Pattern pattern;

RegexPipeline(final Pattern pattern, final Filter[] filters,
final HttpServlet servlet) {
super(filters, servlet);
this.pattern = pattern;
}

boolean match(final HttpServletRequest req) {
final String pathInfo = req.getPathInfo();
return pathInfo != null && pattern.matcher(pathInfo).matches();
}

@Override
void service(HttpServletRequest req, HttpServletResponse rsp)
throws ServletException, IOException {
final String reqInfo = req.getPathInfo();
if (reqInfo == null) {
rsp.sendError(SC_NOT_FOUND);
return;
}

final Matcher cur = pattern.matcher(reqInfo);
if (!cur.matches()) {
rsp.sendError(SC_NOT_FOUND);
return;
}

final String reqPath = req.getServletPath();
final Object old = req.getAttribute(REGEX_GROUPS);
try {
if (1 <= cur.groupCount()) {
// If there are groups extract every capture group and
// build a request for them so RegexGroupFilter can pick
// a different capture group later. Continue using the
// first capture group as the path info.
WrappedRequest groups[] = new WrappedRequest[cur.groupCount()];
for (int groupId = 1; groupId <= cur.groupCount(); groupId++) {
final int s = cur.start(groupId);
final String path, info;

path = reqPath + reqInfo.substring(0, s);
info = cur.group(groupId);
groups[groupId - 1] = new WrappedRequest(req, path, info);
}
req.setAttribute(REGEX_GROUPS, groups);
super.service(groups[0], rsp);

} else {
// No capture groups were present, service the whole request.
final String path = reqPath + reqInfo;
final String info = null;
super.service(new WrappedRequest(req, path, info), rsp);
}
} finally {
if (old != null)
req.setAttribute(REGEX_GROUPS, old);
else
req.removeAttribute(REGEX_GROUPS);
}
}

@Override
public String toString() {
return "Pipeline[regex: " + pattern + " ]";
}
}

+ 63
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinder.java View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import javax.servlet.Filter;
import javax.servlet.http.HttpServlet;

/** Binds a servlet to a URL. */
public interface ServletBinder {
/**
* @param filter
* the filter to trigger while processing the path.
* @return {@code this}.
*/
public ServletBinder through(Filter filter);

/**
* @param servlet
* the servlet to execute on this path.
*/
public void with(HttpServlet servlet);
}

+ 92
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinderImpl.java View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;

abstract class ServletBinderImpl implements ServletBinder {
private final List<Filter> filters;

private HttpServlet httpServlet;

ServletBinderImpl() {
this.filters = new ArrayList<Filter>();
}

public ServletBinder through(Filter filter) {
if (filter == null)
throw new NullPointerException("filter must not be null");
filters.add(filter);
return this;
}

public void with(HttpServlet servlet) {
if (servlet == null)
throw new NullPointerException("servlet must not be null");
if (httpServlet != null)
throw new IllegalStateException("servlet was already bound");
httpServlet = servlet;
}

/** @return the configured servlet, or singleton returning 404 if none. */
protected HttpServlet getServlet() {
if (httpServlet != null)
return httpServlet;
else
return new ErrorServlet(HttpServletResponse.SC_NOT_FOUND);
}

/** @return the configured filters; zero-length array if none. */
protected Filter[] getFilters() {
return filters.toArray(new Filter[filters.size()]);
}

/** @return the pipeline that matches and executes this chain. */
abstract UrlPipeline create();
}

+ 108
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/SuffixPipeline.java View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Selects requests by matching the suffix of the URI.
* <p>
* The suffix string is literally matched against the path info of the servlet
* request, as this class assumes it is invoked by {@link MetaServlet}. Suffix
* strings may include path components. Examples include {@code /info/refs}, or
* just simple extension matches like {@code .txt}.
* <p>
* When dispatching to the rest of the pipeline the HttpServletRequest is
* modified so that {@code getPathInfo()} does not contain the suffix that
* caused this pipeline to be selected.
*/
class SuffixPipeline extends UrlPipeline {
static class Binder extends ServletBinderImpl {
private final String suffix;

Binder(final String suffix) {
this.suffix = suffix;
}

UrlPipeline create() {
return new SuffixPipeline(suffix, getFilters(), getServlet());
}
}

private final String suffix;

private final int suffixLen;

SuffixPipeline(final String suffix, final Filter[] filters,
final HttpServlet servlet) {
super(filters, servlet);
this.suffix = suffix;
this.suffixLen = suffix.length();
}

boolean match(final HttpServletRequest req) {
final String pathInfo = req.getPathInfo();
return pathInfo != null && pathInfo.endsWith(suffix);
}

@Override
void service(HttpServletRequest req, HttpServletResponse rsp)
throws ServletException, IOException {
String curInfo = req.getPathInfo();
String newPath = req.getServletPath() + curInfo;
String newInfo = curInfo.substring(0, curInfo.length() - suffixLen);
super.service(new WrappedRequest(req, newPath, newInfo), rsp);
}

@Override
public String toString() {
return "Pipeline[ *" + suffix + " ]";
}
}

+ 264
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/UrlPipeline.java View File

@@ -0,0 +1,264 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import java.io.IOException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Encapsulates the entire serving stack for a single URL.
* <p>
* Subclasses provide the implementation of {@link #match(HttpServletRequest)},
* which is called by {@link MetaServlet} in registration order to determine the
* pipeline that will be used to handle a request.
* <p>
* The very bottom of each pipeline is a single {@link HttpServlet} that will
* handle producing the response for this pipeline's URL. {@link Filter}s may
* also be registered and applied around the servlet's processing, to manage
* request attributes, set standard response headers, or completely override the
* response generation.
*/
abstract class UrlPipeline {
/** Filters to apply around {@link #servlet}; may be empty but never null. */
private final Filter[] filters;

/** Instance that must generate the response; never null. */
private final HttpServlet servlet;

UrlPipeline(final Filter[] filters, final HttpServlet servlet) {
this.filters = filters;
this.servlet = servlet;
}

/**
* Initialize all contained filters and servlets.
*
* @param context
* the servlet container context our {@link MetaServlet} is
* running within.
* @param inited
* <i>(input/output)</i> the set of filters and servlets which
* have already been initialized within the container context. If
* those same instances appear in this pipeline they are not
* initialized a second time. Filters and servlets that are first
* initialized by this pipeline will be added to this set.
* @throws ServletException
* a filter or servlet is unable to initialize.
*/
void init(final ServletContext context, final Set<Object> inited)
throws ServletException {
for (Filter ref : filters)
initFilter(ref, context, inited);
initServlet(servlet, context, inited);
}

private static void initFilter(final Filter ref,
final ServletContext context, final Set<Object> inited)
throws ServletException {
if (!inited.contains(ref)) {
ref.init(new FilterConfig() {
public String getInitParameter(String name) {
return null;
}

public Enumeration getInitParameterNames() {
return new Enumeration<String>() {
public boolean hasMoreElements() {
return false;
}

public String nextElement() {
throw new NoSuchElementException();
}
};
}

public ServletContext getServletContext() {
return context;
}

public String getFilterName() {
return ref.getClass().getName();
}
});
inited.add(ref);
}
}

private static void initServlet(final HttpServlet ref,
final ServletContext context, final Set<Object> inited)
throws ServletException {
if (!inited.contains(ref)) {
ref.init(new ServletConfig() {
public String getInitParameter(String name) {
return null;
}

public Enumeration getInitParameterNames() {
return new Enumeration<String>() {
public boolean hasMoreElements() {
return false;
}

public String nextElement() {
throw new NoSuchElementException();
}
};
}

public ServletContext getServletContext() {
return context;
}

public String getServletName() {
return ref.getClass().getName();
}
});
inited.add(ref);
}
}

/**
* Destroy all contained filters and servlets.
*
* @param destroyed
* <i>(input/output)</i> the set of filters and servlets which
* have already been destroyed within the container context. If
* those same instances appear in this pipeline they are not
* destroyed a second time. Filters and servlets that are first
* destroyed by this pipeline will be added to this set.
*/
void destroy(final Set<Object> destroyed) {
for (Filter ref : filters)
destroyFilter(ref, destroyed);
destroyServlet(servlet, destroyed);
}

private static void destroyFilter(Filter ref, Set<Object> destroyed) {
if (!destroyed.contains(ref)) {
ref.destroy();
destroyed.add(ref);
}
}

private static void destroyServlet(HttpServlet ref, Set<Object> destroyed) {
if (!destroyed.contains(ref)) {
ref.destroy();
destroyed.add(ref);
}
}

/**
* Determine if this pipeline handles the request's URL.
* <p>
* This method should match on the request's {@code getPathInfo()} method,
* as {@link MetaServlet} passes the request along as-is to each pipeline's
* match method.
*
* @param req
* current HTTP request being considered by {@link MetaServlet}.
* @return {@code true} if this pipeline is configured to handle the
* request; {@code false} otherwise.
*/
abstract boolean match(HttpServletRequest req);

/**
* Execute the filters and the servlet on the request.
* <p>
* Invoked by {@link MetaServlet} once {@link #match(HttpServletRequest)}
* has determined this pipeline is the correct pipeline to handle the
* current request.
*
* @param req
* current HTTP request.
* @param rsp
* current HTTP response.
* @throws ServletException
* request cannot be completed.
* @throws IOException
* IO error prevents the request from being completed.
*/
void service(HttpServletRequest req, HttpServletResponse rsp)
throws ServletException, IOException {
if (0 < filters.length)
new Chain(filters, servlet).doFilter(req, rsp);
else
servlet.service(req, rsp);
}

private static class Chain implements FilterChain {
private final Filter[] filters;

private final HttpServlet servlet;

private int filterIdx;

Chain(final Filter[] filters, final HttpServlet servlet) {
this.filters = filters;
this.servlet = servlet;
}

public void doFilter(ServletRequest req, ServletResponse rsp)
throws IOException, ServletException {
if (filterIdx < filters.length)
filters[filterIdx++].doFilter(req, rsp, this);
else
servlet.service(req, rsp);
}
}
}

+ 87
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.glue;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/** Overrides the path and path info. */
public class WrappedRequest extends HttpServletRequestWrapper {
private final String path;

private final String pathInfo;

/**
* Create a new request with different path and path info properties.
*
* @param originalRequest
* the original HTTP request.
* @param path
* new servlet path to report to callers.
* @param pathInfo
* new path info to report to callers.
*/
public WrappedRequest(final HttpServletRequest originalRequest,
final String path, final String pathInfo) {
super(originalRequest);
this.path = path;
this.pathInfo = pathInfo;
}

@Override
public String getPathTranslated() {
final String p = getPathInfo();
return p != null ? getRealPath(p) : null;
}

@Override
public String getPathInfo() {
return pathInfo;
}

@Override
public String getServletPath() {
return path;
}
}

+ 126
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.resolver;

import javax.servlet.http.HttpServletRequest;

import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.Config.SectionParser;

/**
* Controls access to bare files in a repository.
* <p>
* Older HTTP clients which do not speak the smart HTTP variant of the Git
* protocol fetch from a repository by directly getting its objects and pack
* files. This class, along with the {@code http.getanyfile} per-repository
* configuration setting, can be used by {@link GitServlet} to control whether
* or not these older clients are permitted to read these direct files.
*/
public class AsIsFileService {
/** Always throws {@link ServiceNotEnabledException}. */
public static final AsIsFileService DISABLED = new AsIsFileService() {
@Override
public void access(HttpServletRequest req, Repository db)
throws ServiceNotEnabledException {
throw new ServiceNotEnabledException();
}
};

private static final SectionParser<ServiceConfig> CONFIG = new SectionParser<ServiceConfig>() {
public ServiceConfig parse(final Config cfg) {
return new ServiceConfig(cfg);
}
};

private static class ServiceConfig {
final boolean enabled;

ServiceConfig(final Config cfg) {
enabled = cfg.getBoolean("http", "getanyfile", true);
}
}

/**
* Determine if {@code http.getanyfile} is enabled in the configuration.
*
* @param db
* the repository to check.
* @return {@code false} if {@code http.getanyfile} was explicitly set to
* {@code false} in the repository's configuration file; otherwise
* {@code true}.
*/
protected static boolean isEnabled(Repository db) {
return db.getConfig().get(CONFIG).enabled;
}

/**
* Determine if access to any bare file of the repository is allowed.
* <p>
* This method silently succeeds if the request is allowed, or fails by
* throwing a checked exception if access should be denied.
* <p>
* The default implementation of this method checks {@code http.getanyfile},
* throwing {@link ServiceNotEnabledException} if it was explicitly set to
* {@code false}, and otherwise succeeding silently.
*
* @param req
* current HTTP request, in case information from the request may
* help determine the access request.
* @param db
* the repository the request would obtain a bare file from.
* @throws ServiceNotEnabledException
* bare file access is not allowed on the target repository, by
* any user, for any reason.
* @throws ServiceNotAuthorizedException
* bare file access is not allowed for this HTTP request and
* repository, such as due to a permission error.
*/
public void access(HttpServletRequest req, Repository db)
throws ServiceNotEnabledException, ServiceNotAuthorizedException {
if (!isEnabled(db))
throw new ServiceNotEnabledException();
}
}

+ 164
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/FileResolver.java View File

@@ -0,0 +1,164 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.resolver;

import java.io.File;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;

/** Default resolver serving from a single root path in local filesystem. */
public class FileResolver implements RepositoryResolver {
private final File basePath;

private final boolean exportAll;

/**
* Create a new resolver for the given path.
*
* @param basePath
* the base path all repositories are rooted under.
* @param exportAll
* if true, exports all repositories, ignoring the check for the
* {@code git-daemon-export-ok} files.
*/
public FileResolver(final File basePath, final boolean exportAll) {
this.basePath = basePath;
this.exportAll = exportAll;
}

public Repository open(final HttpServletRequest req,
final String repositoryName) throws RepositoryNotFoundException,
ServiceNotEnabledException {
if (isUnreasonableName(repositoryName))
throw new RepositoryNotFoundException(repositoryName);

final Repository db;
try {
final File gitdir = new File(basePath, repositoryName);
db = RepositoryCache.open(FileKey.lenient(gitdir), true);
} catch (IOException e) {
throw new RepositoryNotFoundException(repositoryName, e);
}

try {
if (isExportOk(req, repositoryName, db)) {
// We have to leak the open count to the caller, they
// are responsible for closing the repository if we
// complete successfully.
return db;
} else
throw new ServiceNotEnabledException();

} catch (RuntimeException e) {
db.close();
throw new RepositoryNotFoundException(repositoryName, e);

} catch (IOException e) {
db.close();
throw new RepositoryNotFoundException(repositoryName, e);

} catch (ServiceNotEnabledException e) {
db.close();
throw e;
}
}

/** @return {@code true} if all repositories are to be exported. */
protected boolean isExportAll() {
return exportAll;
}

/**
* Check if this repository can be served over HTTP.
* <p>
* The default implementation of this method returns true only if either
* {@link #isExportAll()} is true, or the {@code git-daemon-export-ok} file
* is present in the repository's directory.
*
* @param req
* the current HTTP request.
* @param repositoryName
* name of the repository, as present in the URL.
* @param db
* the opened repository instance.
* @return true if the repository is accessible; false if not.
* @throws IOException
* the repository could not be accessed, the caller will claim
* the repository does not exist.
*/
protected boolean isExportOk(HttpServletRequest req, String repositoryName,
Repository db) throws IOException {
if (isExportAll())
return true;
else
return new File(db.getDirectory(), "git-daemon-export-ok").exists();
}

private static boolean isUnreasonableName(final String name) {
if (name.length() == 0)
return true; // no empty paths

if (name.indexOf('\\') >= 0)
return true; // no windows/dos style paths
if (new File(name).isAbsolute())
return true; // no absolute paths

if (name.startsWith("../"))
return true; // no "l../etc/passwd"
if (name.contains("/../"))
return true; // no "foo/../etc/passwd"
if (name.contains("/./"))
return true; // "foo/./foo" is insane to ask
if (name.contains("//"))
return true; // double slashes is sloppy, don't use it

return false; // is a reasonable name
}
}

+ 77
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/RepositoryResolver.java View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.resolver;

import javax.servlet.http.HttpServletRequest;

import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository;

/** Locate a Git {@link Repository} by name from the URL. */
public interface RepositoryResolver {
/**
* Locate and open a reference to a {@link Repository}.
* <p>
* The caller is responsible for closing the returned Repository.
*
* @param req
* the current HTTP request, may be used to inspect session state
* including cookies or user authentication.
* @param name
* name of the repository, as parsed out of the URL.
* @return the opened repository instance, never null.
* @throws RepositoryNotFoundException
* the repository does not exist or the name is incorrectly
* formatted as a repository name.
* @throws ServiceNotAuthorizedException
* the repository exists, but HTTP access is not allowed for the
* current user.
* @throws ServiceNotEnabledException
* the repository exists, but HTTP access is not allowed on the
* target repository, by any user.
*/
Repository open(HttpServletRequest req, String name)
throws RepositoryNotFoundException, ServiceNotAuthorizedException,
ServiceNotEnabledException;
}

+ 54
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/ServiceNotAuthorizedException.java View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.resolver;

/** Indicates the request service is not authorized for current user. */
public class ServiceNotAuthorizedException extends Exception {
private static final long serialVersionUID = 1L;

/** Indicates the request service is not available. */
public ServiceNotAuthorizedException() {
super("Service not permitted");
}
}

+ 54
- 0
org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/ServiceNotEnabledException.java View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.eclipse.jgit.http.server.resolver;

/** Indicates the request service is not enabled on a repository. */
public class ServiceNotEnabledException extends Exception {
private static final long serialVersionUID = 1L;

/** Indicates the request service is not available. */
public ServiceNotEnabledException() {
super("Service not enabled");
}
}

+ 30
- 2
org.eclipse.jgit/src/org/eclipse/jgit/errors/RepositoryNotFoundException.java View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009, Google Inc.
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -59,6 +59,18 @@ public class RepositoryNotFoundException extends TransportException {
this(location.getPath());
}

/**
* Constructs an exception indicating a local repository does not exist.
*
* @param location
* description of the repository not found, usually file path.
* @param why
* why the repository does not exist.
*/
public RepositoryNotFoundException(final File location, Throwable why) {
this(location.getPath(), why);
}

/**
* Constructs an exception indicating a local repository does not exist.
*
@@ -66,6 +78,22 @@ public class RepositoryNotFoundException extends TransportException {
* description of the repository not found, usually file path.
*/
public RepositoryNotFoundException(final String location) {
super("repository not found: " + location);
super(message(location));
}

/**
* Constructs an exception indicating a local repository does not exist.
*
* @param location
* description of the repository not found, usually file path.
* @param why
* why the repository does not exist.
*/
public RepositoryNotFoundException(String location, Throwable why) {
super(message(location), why);
}

private static String message(final String location) {
return "repository not found: " + location;
}
}

+ 5
- 14
org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java View File

@@ -1,7 +1,7 @@
/*
* Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
* Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
* Copyright (C) 2008-2009, Google Inc.
* Copyright (C) 2008-2010, Google Inc.
* Copyright (C) 2009, Google, Inc.
* Copyright (C) 2009, JetBrains s.r.o.
* Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
@@ -298,20 +298,11 @@ public class Config {
String n = getRawString(section, subsection, name);
if (n == null)
return defaultValue;

if (MAGIC_EMPTY_VALUE == n || StringUtils.equalsIgnoreCase("yes", n)
|| StringUtils.equalsIgnoreCase("true", n)
|| StringUtils.equalsIgnoreCase("1", n)
|| StringUtils.equalsIgnoreCase("on", n)) {
if (MAGIC_EMPTY_VALUE == n)
return true;

} else if (StringUtils.equalsIgnoreCase("no", n)
|| StringUtils.equalsIgnoreCase("false", n)
|| StringUtils.equalsIgnoreCase("0", n)
|| StringUtils.equalsIgnoreCase("off", n)) {
return false;

} else {
try {
return StringUtils.toBoolean(n);
} catch (IllegalArgumentException err) {
throw new IllegalArgumentException("Invalid boolean value: "
+ section + "." + name + "=" + n);
}

+ 58
- 0
org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java View File

@@ -1,4 +1,5 @@
/*
* Copyright (C) 2010, Google Inc.
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* and other copyright owners as documented in the project's IP log.
*
@@ -55,6 +56,63 @@ import java.net.URLEncoder;

/** Extra utilities to support usage of HTTP. */
public class HttpSupport {
/** The {@code POST} HTTP method. */
public static final String METHOD_POST = "POST";

/** The {@code Cache-Control} header. */
public static final String HDR_CACHE_CONTROL = "Cache-Control";

/** The {@code Pragma} header. */
public static final String HDR_PRAGMA = "Pragma";

/** The {@code Date} header. */
public static final String HDR_DATE = "Date";

/** The {@code Expires} header. */
public static final String HDR_EXPIRES = "Expires";

/** The {@code ETag} header. */
public static final String HDR_ETAG = "ETag";

/** The {@code If-None-Match} header. */
public static final String HDR_IF_NONE_MATCH = "If-None-Match";

/** The {@code Last-Modified} header. */
public static final String HDR_LAST_MODIFIED = "Last-Modified";

/** The {@code If-Modified-Since} header. */
public static final String HDR_IF_MODIFIED_SINCE = "If-Modified-Since";

/** The {@code Content-Type} header. */
public static final String HDR_CONTENT_TYPE = "Content-Type";

/** The {@code Content-Length} header. */
public static final String HDR_CONTENT_LENGTH = "Content-Length";

/** The {@code Content-Encoding} header. */
public static final String HDR_CONTENT_ENCODING = "Content-Encoding";

/** The {@code Content-Range} header. */
public static final String HDR_CONTENT_RANGE = "Content-Range";

/** The {@code Accept-Ranges} header. */
public static final String HDR_ACCEPT_RANGES = "Accept-Ranges";

/** The {@code If-Range} header. */
public static final String HDR_IF_RANGE = "If-Range";

/** The {@code Range} header. */
public static final String HDR_RANGE = "Range";

/** The {@code Accept-Encoding} header. */
public static final String HDR_ACCEPT_ENCODING = "Accept-Encoding";

/** The {@code gzip} encoding value for {@link #HDR_ACCEPT_ENCODING}. */
public static final String ENCODING_GZIP = "gzip";

/** The standard {@code text/plain} MIME type. */
public static final String TEXT_PLAIN = "text/plain";

/**
* URL encode a value string into an output buffer.
*

+ 39
- 0
org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java View File

@@ -115,6 +115,45 @@ public final class StringUtils {
return true;
}

/**
* Parse a string as a standard Git boolean value.
* <p>
* The terms {@code yes}, {@code true}, {@code 1}, {@code on} can all be
* used to mean {@code true}.
* <p>
* The terms {@code no}, {@code false}, {@code 0}, {@code off} can all be
* used to mean {@code false}.
* <p>
* Comparisons ignore case, via {@link #equalsIgnoreCase(String, String)}.
*
* @param stringValue
* the string to parse.
* @return the boolean interpretation of {@code value}.
* @throws IllegalArgumentException
* if {@code value} is not recognized as one of the standard
* boolean names.
*/
public static boolean toBoolean(final String stringValue) {
if (stringValue == null)
throw new NullPointerException("Expected boolean string value");

if (equalsIgnoreCase("yes", stringValue)
|| equalsIgnoreCase("true", stringValue)
|| equalsIgnoreCase("1", stringValue)
|| equalsIgnoreCase("on", stringValue)) {
return true;

} else if (equalsIgnoreCase("no", stringValue)
|| equalsIgnoreCase("false", stringValue)
|| equalsIgnoreCase("0", stringValue)
|| equalsIgnoreCase("off", stringValue)) {
return false;

} else {
throw new IllegalArgumentException("Not a boolean: " + stringValue);
}
}

private StringUtils() {
// Do not create instances
}

+ 11
- 1
pom.xml View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009, Google Inc.
Copyright (C) 2009-2010, Google Inc.
and other copyright owners as documented in the project's IP log.

This program and the accompanying materials are made available
@@ -135,6 +135,9 @@

<args4j-CQ>CQ 3454</args4j-CQ>
<args4j-version>2.0.12</args4j-version>

<servlet-api-CQ>CQ 3565</servlet-api-CQ>
<servlet-api-version>2.5</servlet-api-version>
</properties>

<build>
@@ -256,6 +259,12 @@
<artifactId>junit</artifactId>
<version>${junit-version}</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api-version}</version>
</dependency>
</dependencies>
</dependencyManagement>

@@ -286,6 +295,7 @@
<modules>
<module>org.eclipse.jgit</module>
<module>org.eclipse.jgit.ui</module>
<module>org.eclipse.jgit.http.server</module>
<module>org.eclipse.jgit.pgm</module>
<module>org.eclipse.jgit.junit</module>
<module>org.eclipse.jgit.test</module>

Loading…
Cancel
Save