├── .gitignore ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── RELEASE.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── org.linkedin.util-core ├── build.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── linkedin │ │ └── util │ │ ├── annotations │ │ ├── Initializable.java │ │ └── Initializer.java │ │ ├── clock │ │ ├── BaseClock.java │ │ ├── Chronos.java │ │ ├── Clock.java │ │ ├── ClockUtils.java │ │ ├── SettableClock.java │ │ ├── SystemClock.java │ │ └── Timespan.java │ │ ├── codec │ │ ├── Base64Codec.java │ │ ├── Codec.java │ │ ├── CodecUtils.java │ │ ├── HexaCodec.java │ │ ├── OneWayCodec.java │ │ └── OneWayMessageDigestCodec.java │ │ ├── collections │ │ ├── CollectionsUtils.java │ │ └── CompoundEnumeration.java │ │ ├── concurrent │ │ ├── ConcurrentUtils.java │ │ ├── ExternalCommand.java │ │ ├── ThreadControl.java │ │ ├── ThreadPerTaskExecutor.java │ │ └── WaitableCounter.java │ │ ├── exceptions │ │ └── InternalException.java │ │ ├── io │ │ ├── GCFile.java │ │ ├── IOUtils.java │ │ ├── ObjectInputStreamWithClassLoader.java │ │ ├── PathUtils.java │ │ ├── ram │ │ │ ├── RAMDirectory.java │ │ │ ├── RAMEntry.java │ │ │ └── RAMFile.java │ │ └── resource │ │ │ ├── AcceptAllResourceFilter.java │ │ │ ├── FileResource.java │ │ │ ├── FilenameEndsWithResourceFilter.java │ │ │ ├── FilteredResource.java │ │ │ ├── JarResource.java │ │ │ ├── NullResource.java │ │ │ ├── RAMResource.java │ │ │ ├── Resource.java │ │ │ ├── ResourceChain.java │ │ │ ├── ResourceFilter.java │ │ │ ├── ResourceInfo.java │ │ │ ├── ResourceNotFoundException.java │ │ │ ├── StaticInfo.java │ │ │ ├── SubDirResourceFilter.java │ │ │ ├── URIResourceFactory.java │ │ │ ├── URIResourceFactoryImpl.java │ │ │ ├── URLResource.java │ │ │ ├── UnsupportedURIException.java │ │ │ └── internal │ │ │ ├── AbstractResource.java │ │ │ ├── AbstractResourceProvider.java │ │ │ ├── FileResourceProvider.java │ │ │ ├── FileURIResourceFactory.java │ │ │ ├── FilteredResourceProvider.java │ │ │ ├── InternalResource.java │ │ │ ├── InternalResourceProvider.java │ │ │ ├── JarResourceProvider.java │ │ │ ├── JarURIResourceFactory.java │ │ │ ├── LeafResource.java │ │ │ ├── LeafResourceImpl.java │ │ │ ├── LocalCacheLeafResource.java │ │ │ ├── NullResourceProvider.java │ │ │ ├── PathBasedResourceProvider.java │ │ │ ├── RAMResourceProvider.java │ │ │ ├── ResourceProvider.java │ │ │ ├── ResourceProviderChain.java │ │ │ ├── SchemeURIResourceFactory.java │ │ │ ├── SchemeURLResourceFactory.java │ │ │ └── URLResourceProvider.java │ │ ├── lang │ │ ├── LangUtils.java │ │ └── MemorySize.java │ │ ├── lifecycle │ │ ├── CannotConfigureException.java │ │ ├── Configurable.java │ │ ├── Destroyable.java │ │ ├── Shutdown.java │ │ ├── ShutdownProxy.java │ │ ├── ShutdownRequestedException.java │ │ ├── Shutdownable.java │ │ ├── Startable.java │ │ └── Terminable.java │ │ ├── reflect │ │ ├── ClassLoaderChain.java │ │ ├── NullClassLoader.java │ │ ├── ObjectProxy.java │ │ ├── ObjectProxyBuilder.java │ │ ├── ObjectProxyInvocationHandler.java │ │ └── ReflectUtils.java │ │ ├── text │ │ ├── IdentityString.java │ │ ├── Indent.java │ │ ├── StringSplitter.java │ │ └── TextUtils.java │ │ ├── url │ │ ├── FilteredURL.java │ │ ├── Query.java │ │ ├── QueryBuilder.java │ │ ├── URL.java │ │ ├── URLBuilder.java │ │ └── URLCodec.java │ │ └── xml │ │ ├── AbstractXMLBuilder.java │ │ ├── XML.java │ │ ├── XMLBuilder.java │ │ ├── XMLIndent.java │ │ └── XMLUtils.java │ └── test │ └── java │ └── org │ └── linkedin │ └── util │ ├── clock │ └── TestTimespan.java │ ├── io │ └── resource │ │ ├── TestNullResource.java │ │ └── TestResource.java │ ├── lang │ └── TestMemorySize.java │ ├── lifecycle │ └── TestShutdown.java │ ├── text │ └── TestStringSplitter.java │ ├── url │ └── TestURLBuilder.java │ └── xml │ └── TestXMLUtils.java ├── org.linkedin.util-groovy ├── build.gradle └── src │ ├── main │ ├── groovy │ │ └── org │ │ │ └── linkedin │ │ │ └── groovy │ │ │ └── util │ │ │ ├── ant │ │ │ ├── AntBuilder6068.groovy │ │ │ └── AntUtils.groovy │ │ │ ├── cli │ │ │ └── CliUtils.groovy │ │ │ ├── collections │ │ │ └── GroovyCollectionsUtils.groovy │ │ │ ├── concurrent │ │ │ └── GroovyConcurrentUtils.groovy │ │ │ ├── config │ │ │ ├── Config.groovy │ │ │ └── MissingConfigParameterException.groovy │ │ │ ├── encryption │ │ │ ├── EncryptedInputStream.groovy │ │ │ └── EncryptionUtils.groovy │ │ │ ├── io │ │ │ ├── DataMaskingInputStream.groovy │ │ │ ├── GroovyIOUtils.groovy │ │ │ └── fs │ │ │ │ ├── FileSystem.groovy │ │ │ │ ├── FileSystemImpl.groovy │ │ │ │ └── SerializableFileResource.groovy │ │ │ ├── ivy │ │ │ └── IvyURLHandler.groovy │ │ │ ├── json │ │ │ └── JsonUtils.groovy │ │ │ ├── lang │ │ │ └── GroovyLangUtils.groovy │ │ │ ├── log │ │ │ ├── JulToSLF4jBridge.groovy │ │ │ ├── MaskDataPatternConverter.groovy │ │ │ ├── MaskDataPatternLayout.groovy │ │ │ └── MaskDataPatternParser.groovy │ │ │ ├── mop │ │ │ └── GroovyMopUtils.groovy │ │ │ ├── net │ │ │ ├── GroovyNetUtils.groovy │ │ │ └── SingletonURLStreamHandlerFactory.groovy │ │ │ ├── rest │ │ │ └── RestException.groovy │ │ │ └── state │ │ │ ├── StateChangeListener.groovy │ │ │ ├── StateMachine.groovy │ │ │ └── StateMachineImpl.groovy │ └── java │ │ └── org │ │ └── linkedin │ │ └── util │ │ └── json │ │ └── jackson │ │ ├── JacksonPrettyPrinter.java │ │ ├── LfNSpacesIndenter.java │ │ └── MetadataStyleSerializerFactory.java │ └── test │ └── groovy │ └── test │ └── util │ ├── collections │ └── TestGroovyCollectionsUtils.groovy │ ├── encryption │ └── TestEncryptionUtils.groovy │ ├── io │ ├── TestGroovyIOUtils.groovy │ └── fs │ │ └── TestFileSystem.groovy │ ├── json │ └── TestJsonUtils.groovy │ ├── lang │ └── TestGroovyLangUtils.groovy │ └── state │ └── TestStateMachine.groovy ├── project-spec.groovy ├── repositories.gradle └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | *.iml 4 | *.ipr 5 | *.iws 6 | build 7 | out 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WARNING WARNING WARNING WARNING 2 | =============================== 3 | 4 | This project is no longer maintained in this repository. To find the latest version of this project, check the [pongasoft/utils-misc](https://github.com/pongasoft/utils-misc) fork. 5 | 6 | WARNING WARNING WARNING WARNING 7 | =============================== 8 | 9 | Introduction 10 | ============ 11 | The project represents a set of utility classes that are used by other LinkedIn open 12 | source projects. 13 | 14 | Compilation 15 | =========== 16 | In order to compile the code you need 17 | 18 | * java 1.6 19 | 20 | At the top simply run 21 | 22 | ./gradlew test 23 | 24 | which should compile and run all the tests. 25 | 26 | IDE Support 27 | =========== 28 | You can issue the command (at the top) 29 | 30 | ./gradlew cleanIdea idea 31 | 32 | which will use the gradle IDEA plugin to create the right set of modules in order to open the 33 | project in IntelliJ IDEA. 34 | 35 | Directory structure 36 | =================== 37 | 38 | * `org.linkedin.util-core` 39 | * Contains a set of java utilities with no external dependencies (except slf4j 40 | for logging). 41 | 42 | * `org.linkedin.util-groovy` 43 | * Contains a set of groovy utilities 44 | 45 | Build configuration 46 | =================== 47 | The project uses the [`org.linkedin.userConfig`](https://github.com/linkedin/gradle-plugins/blob/master/README.md) plugin and as such can be configured 48 | 49 | Example: 50 | ~/.userConfig.properties 51 | top.build.dir="/Volumes/Disk2/deployment/${userConfig.project.name}" 52 | top.install.dir="/export/content/${userConfig.project.name}" 53 | top.release.dir="/export/content/repositories/release" 54 | top.publish.dir="/export/content/repositories/publish" -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | 1.9.0 (2013/04/01) 2 | ------------------ 3 | * implemented [ticket #11](https://github.com/linkedin/linkedin-utils/issues/11): _Upgrade to latest versions_ 4 | 5 | This version uses groovy 2.0.7 under the cover and contains a workaround for an issue (with this version of groovy) when using ``AntBuilder``. 6 | 7 | 1.8.1 (2012/09/20) 8 | ------------------ 9 | * fixed [bug #10](https://github.com/linkedin/linkedin-utils/issues/10): _FileSystem not handling symlinks properly_ 10 | 11 | 1.8.0 (2012/03/31) 12 | ------------------ 13 | * implemented [ticket #6](https://github.com/linkedin/linkedin-utils/issues/6): _Using Jackson JSON (de)serializer_ (thanks for the help from Zoran @ LinkedIn) 14 | * fixed [bug #7](https://github.com/linkedin/linkedin-utils/issues/7): _ArrayList.size field does not exist on other JVMs but sun's_ 15 | 16 | This version uses Jackson Json parser which improves speed and memory consumption when reading/writing JSON. 17 | 18 | Note that ``prettyPrint`` returns a slightly different output than before (keys are still sorted). 19 | 20 | 1.7.2 (2012/01/27) 21 | ------------------ 22 | * fixed [bug #5](https://github.com/linkedin/linkedin-utils/issues/5): _no Authorization header should be generated in fetchContent when not present_ 23 | 24 | 1.7.1 (2011/09/20) 25 | ------------------ 26 | * fixed [bug #4](https://github.com/linkedin/linkedin-utils/issues/4): _GroovyIOUtils.toFile handles groovy string differently_ 27 | 28 | 1.7.0 (2011/06/12) 29 | ------------------ 30 | * added notions of depth and distance to state machine 31 | 32 | 1.6.2 (2011/05/27) 33 | ------------------ 34 | * fixed [bug #3](https://github.com/linkedin/linkedin-utils/issues/3): _IvyURLHandler is not thread safe_ 35 | 36 | 1.6.1 (2011/05/23) 37 | ------------------ 38 | * fixed [bug #2](https://github.com/linkedin/linkedin-utils/issues/2): _ClassCastException when error is a String_ 39 | 40 | 1.6.0 (2011/05/04) 41 | ------------------ 42 | * added more flavors of `noException` method + testing 43 | 44 | 1.5.0 (2011/05/03) 45 | ------------------ 46 | * made `safeOverwrite` more robust 47 | * added test for `safeOverwrite` 48 | * added `GroovyLanUtils.noException` convenient call 49 | 50 | 1.4.0 (2011/04/30) 51 | ------------------ 52 | * fixed [bug #1](https://github.com/linkedin/linkedin-utils/issues/1): _GroovyIOUtils.cat leaks memory_ 53 | 54 | revisited several concepts dealing with the creation of temporary files 55 | 56 | 1.3.0 (2011/01/17) 57 | ------------------ 58 | * fixed `FileSystemImpl.chmod` to handle directories properly 59 | * added `FileSystem.safeOverwrite` and use it in the implementation 60 | * added `GroovyIOUtils.fetchContent` which handles basic authentication properly 61 | 62 | 1.2.1 (2010/12/20) 63 | ------------------ 64 | * use of `gradle-plugins 1.5.0` in order to support `gradle 0.9` (no version change as the code did not change) 65 | 66 | 1.2.1 (2010/12/07) 67 | ------------------ 68 | * `DataMaskingInputStream` handles file of format `key=xxx value=yyy` in addition to `name=xxx value=yyyy` 69 | 70 | 1.0.0 (2010/11/05) 71 | ------------------ 72 | * First release -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * Portions Copyright (c) 2013 Yan Pujante 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | 18 | buildscript { 19 | repositories { 20 | if(project.hasProperty('maven.buildscript.repository')) 21 | { 22 | mavenRepo url: new File(project.properties["maven.buildscript.repository"]).toURI() 23 | } 24 | 25 | if(project.hasProperty('ivy.buildscript.repository')) 26 | { 27 | add(new org.apache.ivy.plugins.resolver.FileSystemResolver()) { 28 | name = "ivy.buildscript.repository" 29 | addIvyPattern "${project.properties['ivy.buildscript.repository']}/[organisation]/[module]/[revision]/[module]-[revision].ivy" 30 | addArtifactPattern "${project.properties['ivy.buildscript.repository']}/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" 31 | m2compatible = true 32 | checkmodified = true 33 | } 34 | } 35 | 36 | // if you want to disallow maven central 37 | if(project.properties['no.maven.central'] != 'true') 38 | { 39 | mavenCentral() 40 | } 41 | } 42 | 43 | dependencies { 44 | classpath 'org.linkedin:org.linkedin.gradle-plugins:1.6.0' 45 | } 46 | } 47 | 48 | apply plugin: 'org.linkedin.userConfig' 49 | apply plugin: 'org.linkedin.spec' 50 | 51 | ext { 52 | topBuildDir = userConfig.top.build.dir ?: "${rootDir}/out/build" 53 | } 54 | 55 | apply plugin: 'org.linkedin.repository' 56 | 57 | allprojects { 58 | apply plugin: 'idea' 59 | group = spec.group 60 | version = spec.version 61 | } 62 | 63 | // we use git 64 | idea.project { 65 | ipr.withXml { root -> 66 | root.asNode().component.find { it.@name == 'VcsDirectoryMappings' }.mapping.@vcs = 'Git' 67 | } 68 | } 69 | 70 | subprojects { 71 | buildscript { 72 | allRepositories.buildscript.configure(repositories) 73 | } 74 | 75 | apply plugin: 'java' 76 | apply plugin: 'maven' 77 | 78 | allRepositories.build.configure(repositories) 79 | 80 | sourceCompatibility = '1.6' 81 | targetCompatibility = '1.6' 82 | 83 | buildDir = "${topBuildDir}${project.path.replace(':','/')}".toString() 84 | } 85 | 86 | task wrapper(type: Wrapper) { 87 | gradleVersion = '1.4' 88 | } 89 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinkedInAttic/linkedin-utils/ca097410b537fb09847c42037593c0f474c0571f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 04 13:58:08 HST 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.4-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /org.linkedin.util-core/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | apply plugin: 'org.linkedin.release' 18 | 19 | 20 | dependencies { 21 | compile spec.external.slf4j 22 | 23 | testCompile spec.external.junit 24 | testRuntime spec.external.slf4jLog4j 25 | } 26 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/annotations/Initializable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.annotations; 19 | 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * The purpose of this annotion is to specify that a public field can be initialized 27 | * prior to use of the instance, during the initialization phase. It should not be modified after the 28 | * fact and there is no guarantee of what will happen if you do. 29 | * 30 | * @author ypujante@linkedin.com 31 | * 32 | */ 33 | @Retention(RetentionPolicy.RUNTIME) 34 | @Target(ElementType.FIELD) 35 | public @interface Initializable 36 | { 37 | /** 38 | * if set to true it means that the field must be initialized prior to use 39 | * the instance as there is no default value. If set to false, it means that 40 | * the field has a default value. 41 | */ 42 | boolean required() default false; 43 | 44 | /** 45 | * Optional description 46 | */ 47 | String description() default ""; 48 | } 49 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/annotations/Initializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.annotations; 19 | 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * The purpose of this annotion is to specify that a public method (usually a setter) should be used 27 | * prior to use the instance, during the initialization phase. It should not be modified after the 28 | * fact and there is no guarantee of what will happen if you do. 29 | * 30 | * @author ypujante@linkedin.com 31 | * 32 | */ 33 | @Retention(RetentionPolicy.RUNTIME) 34 | @Target(ElementType.METHOD) 35 | public @interface Initializer 36 | { 37 | /** 38 | * if set to true it means that the setter must be called prior to use 39 | * the instance. If set to false, it means that the field has a default value. 40 | */ 41 | boolean required() default false; 42 | 43 | /** 44 | * Optional description 45 | */ 46 | String description() default ""; 47 | } 48 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/clock/BaseClock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.clock; 18 | 19 | import java.util.Date; 20 | import java.io.Serializable; 21 | 22 | /** 23 | * Basic implementation of a clock. 24 | * 25 | * @author ypujante@linkedin.com 26 | */ 27 | public abstract class BaseClock implements Clock, Serializable 28 | { 29 | private static final long serialVersionUID = 1L; 30 | 31 | /** 32 | * Constructor */ 33 | public BaseClock() 34 | { 35 | } 36 | 37 | /** 38 | * @return the current date of this clock. */ 39 | @Override 40 | public Date currentDate() 41 | { 42 | return new Date(currentTimeMillis()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/clock/Chronos.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.clock; 18 | 19 | import java.io.PrintWriter; 20 | import java.io.OutputStream; 21 | 22 | /** 23 | * This class is used to measure time intervals... Each time you tick, you 24 | * get the amount of time ellapsed since the last one 25 | * 26 | * 27 | * @author ypujante@linkedin.com */ 28 | public class Chronos 29 | { 30 | /** 31 | * Where to print information 32 | */ 33 | private final PrintWriter _str; 34 | 35 | /** 36 | * The last tick 37 | */ 38 | private long _tick = 0; 39 | 40 | /** 41 | * When the chronos is started */ 42 | private long _startTime; 43 | 44 | /** 45 | * The clock to use */ 46 | private final Clock _clock; 47 | 48 | /** 49 | * Constructor : initialize the tick and sets no stream */ 50 | public Chronos() 51 | { 52 | this((PrintWriter) null); 53 | } 54 | 55 | /** 56 | * Constructor : initialize the tick and set the stream to the one given 57 | * 58 | * @param str the print stream for the output */ 59 | public Chronos(PrintWriter str) 60 | { 61 | this(new SystemClock(), str); 62 | } 63 | 64 | /** 65 | * Constructor : initialize the tick and set the stream to the one given 66 | * 67 | * @param str the print stream for the output */ 68 | public Chronos(OutputStream str) 69 | { 70 | this(new PrintWriter(str)); 71 | } 72 | 73 | /** 74 | * Constructor : initialize the tick and sets no stream */ 75 | public Chronos(Clock clock) 76 | { 77 | this(clock, (PrintWriter) null); 78 | } 79 | 80 | /** 81 | * Constructor : initialize the tick and set the stream to the one given 82 | * 83 | * @param str the print stream for the output */ 84 | public Chronos(Clock clock, PrintWriter str) 85 | { 86 | _str = str; 87 | _clock = clock; 88 | _startTime = _clock.currentTimeMillis(); 89 | tick(); 90 | } 91 | 92 | /** 93 | * Constructor : initialize the tick and set the stream to the one given 94 | * 95 | * @param str the print stream for the output */ 96 | public Chronos(Clock clock, OutputStream str) 97 | { 98 | this(clock, new PrintWriter(str)); 99 | } 100 | 101 | /** 102 | * Returns the number of milliseconds ellapsed since the last call to 103 | * this function. 104 | * 105 | * @return the number of milliseconds since last call*/ 106 | public long tick() 107 | { 108 | long tick = _clock.currentTimeMillis(); 109 | long diff = tick - _tick; 110 | 111 | _tick = tick; 112 | 113 | return diff; 114 | } 115 | 116 | /** 117 | * @return the total time since start of this chronos */ 118 | public long getTotalTime() 119 | { 120 | return _clock.currentTimeMillis() - _startTime; 121 | } 122 | 123 | /** 124 | * Display the time ellapsed since the last call (with no message) */ 125 | public void displayElapsedTime() 126 | { 127 | this.displayElapsedTime(""); 128 | } 129 | 130 | /** 131 | * Display the time ellapsed since the last call (with an additional 132 | * message) 133 | * 134 | * @param mess the message to display first */ 135 | public void displayElapsedTime(String mess) 136 | { 137 | if(_str != null) 138 | _str.println(mess + getElapsedTime()); 139 | } 140 | 141 | /** 142 | * Returns a string that represents the time elapsed 143 | * 144 | * @return the elapsed time as a string */ 145 | public String getElapsedTime() 146 | { 147 | StringBuilder sb = new StringBuilder("Time: "); 148 | sb.append(this.tick()); 149 | sb.append(" ms"); 150 | 151 | return sb.toString(); 152 | } 153 | 154 | /** 155 | * @return the elapsed time as hour/minute/second */ 156 | public String getElapsedTimeAsHMS() 157 | { 158 | return new Timespan(tick()).getCanonicalString(); 159 | } 160 | 161 | /** 162 | * Flushes the underlying writer */ 163 | public void flush() 164 | { 165 | if(_str != null) 166 | _str.flush(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/clock/Clock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.clock; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * Abstraction of a clock. 23 | * 24 | * @author ypujante@linkedin.com 25 | */ 26 | public interface Clock 27 | { 28 | // some commonly used constants 29 | public static final long SECOND_IN_MS = Timespan.TimeUnit.SECOND.getMillisecondsCount(); 30 | public static final long MINUTE_IN_MS = Timespan.TimeUnit.MINUTE.getMillisecondsCount(); 31 | public static final long HOUR_IN_MS = Timespan.TimeUnit.HOUR.getMillisecondsCount(); 32 | public static final long DAY_IN_MS = Timespan.TimeUnit.DAY.getMillisecondsCount(); 33 | 34 | /** 35 | * @return the current time of this clock in milliseconds. */ 36 | long currentTimeMillis(); 37 | 38 | /** 39 | * @return the current date of this clock. */ 40 | Date currentDate(); 41 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/clock/ClockUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.clock; 19 | 20 | /** 21 | * @author ypujante@linkedin.com 22 | * 23 | */ 24 | public class ClockUtils 25 | { 26 | /** 27 | * Converts the object into a timespan. If already a timespan then simply return the object. 28 | * Otherwise call {@link Timespan#parse(String)} on t.toString(). Works well for 29 | * long and String 30 | * 31 | * @return a timespan (null if t is null) 32 | */ 33 | public static Timespan toTimespan(Object t) 34 | { 35 | if(t == null) 36 | return null; 37 | 38 | if(t instanceof Timespan) 39 | { 40 | return (Timespan) t; 41 | } 42 | 43 | return Timespan.parse(t.toString()); 44 | } 45 | 46 | /** 47 | * Computes the end time = now + timeout 48 | * 49 | * @param timeout (see {@link #toTimespan(Object)}) 50 | */ 51 | public static long toEndTime(Object timeout) 52 | { 53 | return toEndTime(null, timeout); 54 | } 55 | 56 | /** 57 | * Computes the end time = now + timeout 58 | * 59 | * @param clock can be null to use system clock 60 | * @param timeout (see {@link #toTimespan(Object)}) 61 | * @return 0 if 62 | */ 63 | public static long toEndTime(Clock clock, Object timeout) 64 | { 65 | Timespan t = toTimespan(timeout); 66 | if(t == null) 67 | return 0; 68 | if(clock == null) 69 | clock = SystemClock.INSTANCE; 70 | 71 | if(t.getDurationInMilliseconds() == 0) 72 | return 0; 73 | 74 | return t.futureTimeMillis(clock); 75 | } 76 | 77 | /** 78 | * Constructor 79 | */ 80 | private ClockUtils() 81 | { 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/clock/SettableClock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.clock; 18 | 19 | /** 20 | * @author ypujante@linkedin.com 21 | * 22 | */ 23 | public class SettableClock extends BaseClock 24 | { 25 | private static final long serialVersionUID = 1L; 26 | 27 | private long _currentTimeMillis; 28 | 29 | private long _checkpointedCurrentTimeMillis = -1; 30 | 31 | /** 32 | * Constructor 33 | */ 34 | public SettableClock() 35 | { 36 | this(System.currentTimeMillis()); 37 | } 38 | 39 | /** 40 | * Constructor 41 | */ 42 | public SettableClock(long currentTimeMillis) 43 | { 44 | setCurrentTimeMillis(currentTimeMillis); 45 | } 46 | 47 | /** 48 | * @return the current time of this clock in milliseconds. 49 | */ 50 | @Override 51 | public long currentTimeMillis() 52 | { 53 | return _currentTimeMillis; 54 | } 55 | 56 | public void setCurrentTimeMillis(long currentTimeMillis) 57 | { 58 | _currentTimeMillis = currentTimeMillis; 59 | } 60 | 61 | public void addDuration(Timespan duration) 62 | { 63 | setCurrentTimeMillis(duration.futureTimeMillis(this)); 64 | } 65 | 66 | public void subtractDuration(Timespan duration) 67 | { 68 | setCurrentTimeMillis(duration.pastTimeMillis(this)); 69 | } 70 | 71 | /** 72 | * Creates a checkpoint (memorizes current time milliseconds) 73 | */ 74 | public void checkpoint() 75 | { 76 | _checkpointedCurrentTimeMillis = _currentTimeMillis; 77 | } 78 | 79 | /** 80 | * Reverts to previous checkpoint 81 | * @return the new current time millis 82 | */ 83 | public long revertToCheckpoint() 84 | { 85 | if(_checkpointedCurrentTimeMillis != -1) 86 | { 87 | _currentTimeMillis = _checkpointedCurrentTimeMillis; 88 | _checkpointedCurrentTimeMillis = -1; 89 | } 90 | return _currentTimeMillis; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/clock/SystemClock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.clock; 18 | 19 | import java.io.Serializable; 20 | 21 | /** 22 | * Implementation of a clock using the system clock. 23 | * 24 | * @author ypujante@linkedin.com 25 | */ 26 | public class SystemClock extends BaseClock implements Serializable 27 | { 28 | private static final long serialVersionUID = 1L; 29 | 30 | public static final SystemClock INSTANCE = new SystemClock(); 31 | 32 | public static SystemClock instance() 33 | { 34 | return INSTANCE; 35 | } 36 | 37 | /** 38 | * Constructor */ 39 | public SystemClock() 40 | { 41 | } 42 | 43 | /** 44 | * @return the current time of this clock in milliseconds. */ 45 | @Override 46 | public long currentTimeMillis() 47 | { 48 | return System.currentTimeMillis(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/codec/Codec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.codec; 18 | 19 | /** 20 | * Defines the API of a codec. There is a method to encode an array of byte 21 | * into a String and one that does the opposite. 22 | * 23 | * @author ypujante@linkedin.com */ 24 | public interface Codec extends OneWayCodec 25 | { 26 | /** 27 | * Defines the exception thrown when the string cannot be decoded */ 28 | public static class CannotDecodeException extends Exception 29 | { 30 | private static final long serialVersionUID = 1L; 31 | 32 | public CannotDecodeException(String msg) 33 | { 34 | super(msg); 35 | } 36 | 37 | public CannotDecodeException(String message, Throwable cause) 38 | { 39 | super(message, cause); 40 | } 41 | } 42 | 43 | /** 44 | * Decodes the String into a byte array 45 | * 46 | * @param s the string to decode 47 | * @return the byte array decoded 48 | * @exception CannotDecodeException if the string has not been encoded 49 | * with this codec */ 50 | public byte[] decode(String s) throws CannotDecodeException; 51 | } 52 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/codec/CodecUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.codec; 19 | 20 | import java.io.UnsupportedEncodingException; 21 | import java.security.MessageDigest; 22 | import java.security.NoSuchAlgorithmException; 23 | import java.util.Random; 24 | 25 | /** 26 | * @author ypujante@linkedin.com 27 | * 28 | */ 29 | public class CodecUtils 30 | { 31 | /** 32 | * Encodes the string using the codec provided. 33 | * 34 | * @param codec encode the string 35 | * @param s the string to encode 36 | * @return the encoded string */ 37 | public static String encodeString(OneWayCodec codec, String s) 38 | { 39 | try 40 | { 41 | return codec.encode(s.getBytes("UTF-8")); 42 | } 43 | catch(UnsupportedEncodingException ex) 44 | { 45 | // shouldn't happen 46 | throw new RuntimeException(ex); 47 | } 48 | } 49 | 50 | /** 51 | * Decodes the string using the codec provided. Returns a string 52 | * 53 | * @param codec encode the string 54 | * @param s the string to encode 55 | * @return the encoded string 56 | * @throws Codec.CannotDecodeException if cannot decode the string */ 57 | public static String decodeString(Codec codec, String s) 58 | throws Codec.CannotDecodeException 59 | { 60 | try 61 | { 62 | return new String(codec.decode(s), "UTF-8"); 63 | } 64 | catch(UnsupportedEncodingException ex) 65 | { 66 | // shouldn't happen 67 | throw new RuntimeException(ex); 68 | } 69 | } 70 | 71 | /** 72 | * Create a Random object by extracting the seed from the password. 73 | */ 74 | public static Random createRandom(String password) 75 | { 76 | if(password == null) 77 | return null; 78 | 79 | byte[] bytes; 80 | 81 | try 82 | { 83 | MessageDigest md = MessageDigest.getInstance("SHA-1"); 84 | bytes = md.digest(password.getBytes("UTF-8")); 85 | } 86 | catch(NoSuchAlgorithmException e) 87 | { 88 | // should not happen 89 | throw new RuntimeException(e); 90 | } 91 | catch(UnsupportedEncodingException e) 92 | { 93 | // should not happen 94 | throw new RuntimeException(e); 95 | } 96 | 97 | int len = bytes.length; 98 | 99 | // we only take at most 6 bytes => 48 bits 100 | if(len > 6) 101 | len = 6; 102 | 103 | long seed = 0; 104 | 105 | if(len > 0) 106 | { 107 | seed = bytes[0]; 108 | 109 | for(int i = 1; i < len; i++) 110 | { 111 | seed <<= 8; 112 | seed |= bytes[i]; 113 | } 114 | } 115 | 116 | int k = 0; 117 | 118 | for(int i = len; i < bytes.length; i++) 119 | { 120 | seed ^= (((long) bytes[i]) << (k * 8)); 121 | if(k++ == 5) 122 | k = 0; 123 | } 124 | 125 | return new Random(seed); 126 | } 127 | 128 | /** 129 | * Constructor 130 | */ 131 | private CodecUtils() 132 | { 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/codec/HexaCodec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.codec; 19 | 20 | import java.math.BigInteger; 21 | 22 | /** 23 | * Simply returns the hexadecimal values of the byte array. 24 | * 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public class HexaCodec implements Codec 29 | { 30 | // stateless, thread safe.. 31 | public static final HexaCodec INSTANCE = new HexaCodec(); 32 | 33 | public static HexaCodec instance() 34 | { 35 | return INSTANCE; 36 | } 37 | 38 | private static String[] HEXA_VALUES = 39 | { 40 | "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d","0e", "0f", 41 | "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d","1e", "1f", 42 | "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d","2e", "2f", 43 | "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d","3e", "3f", 44 | "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d","4e", "4f", 45 | "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d","5e", "5f", 46 | "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d","6e", "6f", 47 | "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d","7e", "7f", 48 | "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d","8e", "8f", 49 | "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d","9e", "9f", 50 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad","ae", "af", 51 | "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd","be", "bf", 52 | "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd","ce", "cf", 53 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd","de", "df", 54 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed","ee", "ef", 55 | "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd","fe", "ff" 56 | }; 57 | 58 | /** 59 | * Constructor 60 | */ 61 | public HexaCodec() 62 | { 63 | } 64 | 65 | /** 66 | * Decodes the String into a byte array 67 | * 68 | * @param s the string to decode 69 | * @return the byte array decoded 70 | * @throws CannotDecodeException if the string has not been encoded with this codec 71 | */ 72 | @Override 73 | public byte[] decode(String s) throws CannotDecodeException 74 | { 75 | if(s == null || s.length() <= 0) 76 | { 77 | throw new CannotDecodeException("Cannot decode null or empty String"); 78 | } 79 | else 80 | { 81 | return new BigInteger(s, 16).toByteArray(); 82 | } 83 | } 84 | 85 | /** 86 | * Encode the array into a String 87 | * 88 | * @param byteArray the array to encode 89 | * @return the encoded String 90 | */ 91 | @Override 92 | public String encode(byte[] byteArray) 93 | { 94 | int len = byteArray.length; 95 | 96 | char[] encoded = new char[len * 2]; 97 | 98 | int j = 0; 99 | for(int i = 0; i < byteArray.length; i++) 100 | { 101 | int b = byteArray[i] & 0xFF; 102 | String hexa = HEXA_VALUES[b]; 103 | encoded[j++] = hexa.charAt(0); 104 | encoded[j++] = hexa.charAt(1); 105 | } 106 | 107 | return new String(encoded); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/codec/OneWayCodec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.codec; 18 | 19 | /** 20 | * A one way codec simply define a method to encode. 21 | * 22 | * @author ypujante@linkedin.com 23 | */ 24 | public interface OneWayCodec 25 | { 26 | /** 27 | * Encode the array into a String 28 | * 29 | * @param byteArray the array to encode 30 | * @return the encoded String */ 31 | String encode(byte[] byteArray); 32 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/collections/CollectionsUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.collections; 18 | 19 | import java.io.File; 20 | import java.io.FileReader; 21 | import java.io.IOException; 22 | import java.io.Reader; 23 | import java.util.EnumSet; 24 | import java.util.Properties; 25 | 26 | /** 27 | * Contains useful global utils methods. 28 | * 29 | * @author ypujante@linkedin.com */ 30 | public class CollectionsUtils 31 | { 32 | /** 33 | * Reverses the array in place. 34 | * @param array the array to reverse 35 | * @return the same array provided NOT a new one! 36 | */ 37 | public static T[] reverse(T[] array) 38 | { 39 | if(array == null) 40 | return array; 41 | 42 | int s = 0; 43 | int e = array.length - 1; 44 | while(s < e) 45 | { 46 | // swap index e and s 47 | T tmp = array[e]; 48 | array[e] = array[s]; 49 | array[s] = tmp; 50 | 51 | s++; 52 | e--; 53 | } 54 | 55 | return array; 56 | } 57 | 58 | /** 59 | * Turns an array of enumeration values into an enum set 60 | * 61 | * @param clazz the type of the enum 62 | * @param ts the array of enums 63 | * @return the enum set containing all the values from the array 64 | */ 65 | public static > EnumSet toEnumSet(Class clazz, T... ts) 66 | { 67 | if(ts == null) 68 | return null; 69 | 70 | EnumSet res = EnumSet.noneOf(clazz); 71 | for(T t : ts) 72 | { 73 | res.add(t); 74 | } 75 | return res; 76 | } 77 | 78 | /** 79 | * Convenient call to load a properties file from the provided file 80 | */ 81 | public static Properties loadProperties(File file) throws IOException 82 | { 83 | if(file == null) 84 | return null; 85 | 86 | FileReader reader = new FileReader(file); 87 | try 88 | { 89 | return loadProperties(reader); 90 | } 91 | finally 92 | { 93 | reader.close(); 94 | } 95 | } 96 | 97 | /** 98 | * Convenient call to load a properties file from the provided reader 99 | */ 100 | public static Properties loadProperties(Reader reader) throws IOException 101 | { 102 | if(reader == null) 103 | return null; 104 | 105 | Properties properties = new Properties(); 106 | properties.load(reader); 107 | return properties; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/collections/CompoundEnumeration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.collections; 19 | 20 | import java.util.Enumeration; 21 | import java.util.NoSuchElementException; 22 | 23 | /** 24 | * @author ypujante@linkedin.com 25 | * 26 | */ /* 27 | * A useful utility class that will enumerate over an array of 28 | * enumerations. 29 | */ 30 | public class CompoundEnumeration implements Enumeration 31 | { 32 | private final Enumeration[] _enums; 33 | private int index = 0; 34 | 35 | public CompoundEnumeration(Enumeration[] enums) 36 | { 37 | _enums = enums; 38 | } 39 | 40 | private boolean next() 41 | { 42 | while(index < _enums.length) 43 | { 44 | if(_enums[index] != null && _enums[index].hasMoreElements()) 45 | { 46 | return true; 47 | } 48 | index++; 49 | } 50 | return false; 51 | } 52 | 53 | @Override 54 | public boolean hasMoreElements() 55 | { 56 | return next(); 57 | } 58 | 59 | @Override 60 | public E nextElement() 61 | { 62 | if(!next()) 63 | { 64 | throw new NoSuchElementException(); 65 | } 66 | return _enums[index].nextElement(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/concurrent/ThreadPerTaskExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.concurrent; 18 | 19 | import java.util.concurrent.Executor; 20 | import java.util.concurrent.ThreadFactory; 21 | import java.util.concurrent.Future; 22 | import java.util.concurrent.Callable; 23 | import java.util.concurrent.FutureTask; 24 | 25 | /** 26 | * This executor simply delegates to the thread factory to create a new thread everytime. 27 | * 28 | * @author ypujante@linkedin.com 29 | * 30 | */ 31 | public class ThreadPerTaskExecutor implements Executor 32 | { 33 | private final ThreadFactory _threadFactory; 34 | 35 | /** 36 | * Constructor 37 | */ 38 | public ThreadPerTaskExecutor() 39 | { 40 | this(new ThreadFactory() 41 | { 42 | @Override 43 | public Thread newThread(Runnable r) 44 | { 45 | return new Thread(r); 46 | } 47 | }); 48 | } 49 | 50 | /** 51 | * Constructor 52 | */ 53 | public ThreadPerTaskExecutor(ThreadFactory threadFactory) 54 | { 55 | _threadFactory = threadFactory; 56 | } 57 | 58 | @Override 59 | public void execute(Runnable task) 60 | { 61 | Thread thread = _threadFactory.newThread(task); 62 | thread.start(); 63 | } 64 | 65 | /** 66 | * Executes the callable in a separate thread and return the future to get the result. Note 67 | * that this implementation is not efficient and should be used very carefully. 68 | * 69 | * @param callable 70 | * @return the future to get the result. 71 | */ 72 | public static Future execute(Callable callable) 73 | { 74 | FutureTask futureTask = new FutureTask(callable); 75 | 76 | new Thread(futureTask).start(); 77 | 78 | return futureTask; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/concurrent/WaitableCounter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.concurrent; 18 | 19 | import org.linkedin.util.annotations.Initializable; 20 | import org.linkedin.util.clock.Clock; 21 | import org.linkedin.util.clock.ClockUtils; 22 | import org.linkedin.util.clock.SystemClock; 23 | 24 | import java.util.concurrent.TimeoutException; 25 | 26 | /** 27 | * This class is a utility class that just encapsulates a counter on which 28 | * you can wait until it reaches 0. 29 | * 30 | * @author ypujante@linkedin.com */ 31 | public class WaitableCounter 32 | { 33 | @Initializable 34 | public Clock clock = SystemClock.INSTANCE; 35 | 36 | private int _counter; 37 | 38 | public WaitableCounter(int counter) 39 | { 40 | _counter = counter; 41 | } 42 | 43 | public WaitableCounter() 44 | { 45 | this(0); 46 | } 47 | 48 | public synchronized void dec() 49 | { 50 | _counter--; 51 | 52 | if(_counter == 0) 53 | notifyAll(); 54 | } 55 | 56 | public synchronized void inc() 57 | { 58 | _counter++; 59 | } 60 | 61 | public synchronized int getCounter() 62 | { 63 | return _counter; 64 | } 65 | 66 | public synchronized void waitForCounter() throws InterruptedException 67 | { 68 | while(_counter > 0) 69 | wait(); 70 | } 71 | 72 | public synchronized void waitForCounter(Object timeout) 73 | throws InterruptedException, TimeoutException 74 | { 75 | long endTime = ClockUtils.toEndTime(clock, timeout); 76 | 77 | while(_counter > 0) 78 | ConcurrentUtils.awaitUntil(clock, this, endTime); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/exceptions/InternalException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.exceptions; 18 | 19 | import java.lang.reflect.InvocationTargetException; 20 | 21 | /** 22 | * Exception thrown when there is an internal problem. Should *not* be used for business style 23 | * exception (bad example: NoSuchMemberException). Usually used to wrap other low 24 | * level exceptions (ex: a SQLException reprensenting the fact that the db is down). 25 | * 26 | * 27 | * @author ypujante@linkedin.com */ 28 | public class InternalException extends RuntimeException 29 | { 30 | private static final long serialVersionUID = 1L; 31 | 32 | public InternalException(String module, Throwable detail) 33 | { 34 | super(module, detail); 35 | } 36 | 37 | public InternalException(String module, String detail) 38 | { 39 | super(module + ":" + detail); 40 | } 41 | 42 | public InternalException(String module, String detail, Throwable th) 43 | { 44 | super(module + ":" + detail, th); 45 | } 46 | 47 | public InternalException(String module) 48 | { 49 | super(module); 50 | } 51 | 52 | public InternalException(Throwable th) 53 | { 54 | super(th); 55 | } 56 | 57 | public InternalException() 58 | { 59 | super(); 60 | } 61 | 62 | /** 63 | * Convenient call to adapt the InvocationTargetException into an 64 | * InternalException 65 | * 66 | * @param module the module 67 | * @param ite the invocation target exception (coming from Method.invoke) 68 | * @throws InternalException this method always throw an exception at the end: either a 69 | * RuntimeException or Error or InternalException 70 | */ 71 | public static InternalException throwInternalException(String module, 72 | InvocationTargetException ite) 73 | throws InternalException 74 | { 75 | try 76 | { 77 | throw ite.getTargetException(); 78 | } 79 | catch(Error e) 80 | { 81 | throw e; 82 | } 83 | catch(RuntimeException e) 84 | { 85 | throw e; 86 | } 87 | catch(Throwable e) 88 | { 89 | throw new InternalException(module, e); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/ObjectInputStreamWithClassLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.io; 19 | 20 | import org.linkedin.util.reflect.ReflectUtils; 21 | 22 | import java.io.ObjectInputStream; 23 | import java.io.InputStream; 24 | import java.io.IOException; 25 | import java.io.ObjectStreamClass; 26 | 27 | /** 28 | * This ObjectInputStream uses provided class loader 29 | * 30 | * @author ypujante@linkedin.com 31 | * 32 | */ 33 | public class ObjectInputStreamWithClassLoader extends ObjectInputStream 34 | { 35 | private final ClassLoader _classLoader; 36 | 37 | public ObjectInputStreamWithClassLoader(InputStream inputStream, ClassLoader classLoader) 38 | throws IOException 39 | { 40 | super(inputStream); 41 | _classLoader = classLoader; 42 | } 43 | 44 | @Override 45 | protected Class resolveClass(ObjectStreamClass osc) 46 | throws IOException, ClassNotFoundException 47 | { 48 | return ReflectUtils.forName(osc.getName(), _classLoader); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/PathUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.io; 19 | 20 | /** 21 | * Utility methods for path related computation. 22 | * 23 | * @author ypujante@linkedin.com 24 | * 25 | */ 26 | public class PathUtils 27 | { 28 | /** 29 | * Adds 2 paths taking into consideration the / 30 | * 31 | * @param path1 32 | * @param path2 33 | * @return path1 + path2 34 | */ 35 | public static String addPaths(String path1, String path2) 36 | { 37 | if(path1.endsWith("/")) 38 | { 39 | if(path2.startsWith("/")) 40 | return path1.substring(0, path1.length() - 1) + path2; 41 | else 42 | return path1 + path2; 43 | } 44 | else 45 | { 46 | if(path2.startsWith("/")) 47 | return path1 + path2; 48 | else 49 | return path1 + "/" + path2; 50 | } 51 | } 52 | 53 | /** 54 | * Adds a leading slash if not already exists 55 | * 56 | * @param path 57 | * @return the path with a leading / 58 | */ 59 | public static String addLeadingSlash(String path) 60 | { 61 | if(!path.startsWith("/")) 62 | return "/" + path; 63 | else 64 | return path; 65 | } 66 | 67 | /** 68 | * Removes a leading slash if exists 69 | * 70 | * @param path 71 | * @return the path without a leading / 72 | */ 73 | public static String removeLeadingSlash(String path) 74 | { 75 | if(path.startsWith("/")) 76 | return path.substring(1); 77 | else 78 | return path; 79 | } 80 | 81 | /** 82 | * Adds a trailing slash if not already exists 83 | * 84 | * @param path 85 | * @return the path with a trailing / 86 | */ 87 | public static String addTrailingSlash(String path) 88 | { 89 | if(!path.endsWith("/")) 90 | return path + "/"; 91 | else 92 | return path; 93 | } 94 | 95 | /** 96 | * Removes a trailing slash if exists 97 | * 98 | * @param path 99 | * @return the path without a trailing / 100 | */ 101 | public static String removeTrailingSlash(String path) 102 | { 103 | if(path.endsWith("/")) 104 | return path.substring(0, path.length() - 1); 105 | else 106 | return path; 107 | } 108 | 109 | /** 110 | * @param path 111 | * @return the parent path given a path 112 | */ 113 | public static String getParentPath(String path) 114 | { 115 | String parentPath = path; 116 | 117 | if("/".equals(parentPath)) 118 | return parentPath; 119 | 120 | parentPath = PathUtils.removeTrailingSlash(parentPath); 121 | 122 | int idx = parentPath.lastIndexOf("/"); 123 | if(idx >= 0) 124 | parentPath = parentPath.substring(0, idx + 1); 125 | else 126 | parentPath = "/"; 127 | 128 | return parentPath; 129 | } 130 | 131 | /** 132 | * Constructor 133 | */ 134 | public PathUtils() 135 | { 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/ram/RAMEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.ram; 18 | 19 | import org.linkedin.util.clock.Clock; 20 | 21 | /** 22 | * @author ypujante@linkedin.com 23 | * 24 | */ 25 | public abstract class RAMEntry 26 | { 27 | protected final Clock _clock; 28 | 29 | private final String _name; 30 | 31 | private long _lastModifiedDate; 32 | 33 | public RAMEntry(Clock clock, String name) 34 | { 35 | this(clock, name, clock.currentTimeMillis()); 36 | } 37 | 38 | public RAMEntry(Clock clock, 39 | String name, 40 | long lastModifiedDate) 41 | { 42 | _clock = clock; 43 | _name = name; 44 | _lastModifiedDate = lastModifiedDate; 45 | } 46 | 47 | public String name() 48 | { 49 | return _name; 50 | } 51 | 52 | public long lastModified() 53 | { 54 | return _lastModifiedDate; 55 | } 56 | 57 | public void touch(long lastModifiedDate) 58 | { 59 | _lastModifiedDate = lastModifiedDate; 60 | } 61 | 62 | public void touch() 63 | { 64 | _lastModifiedDate = _clock.currentTimeMillis(); 65 | } 66 | 67 | public abstract long getContentLength(); 68 | } 69 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/ram/RAMFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.ram; 18 | 19 | import org.linkedin.util.clock.Clock; 20 | 21 | /** 22 | * @author ypujante@linkedin.com 23 | * 24 | */ 25 | public class RAMFile extends RAMEntry 26 | { 27 | private final byte[] _content; 28 | 29 | 30 | public RAMFile(Clock clock, String name, byte[] content) 31 | { 32 | super(clock, name); 33 | _content = content; 34 | } 35 | 36 | public RAMFile(Clock clock, String name, long lastModifiedDate, byte[] content) 37 | { 38 | super(clock, name, lastModifiedDate); 39 | _content = content; 40 | } 41 | 42 | public byte[] getContent() 43 | { 44 | return _content; 45 | } 46 | 47 | @Override 48 | public long getContentLength() 49 | { 50 | return _content.length; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/AcceptAllResourceFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | /** 20 | * @author ypujante@linkedin.com 21 | * 22 | */ 23 | public class AcceptAllResourceFilter implements ResourceFilter 24 | { 25 | /** 26 | * Stateless => can share an instance 27 | */ 28 | public static final AcceptAllResourceFilter INSTANCE = new AcceptAllResourceFilter(); 29 | 30 | /** 31 | * Tests whether this resource should be included in the result. 32 | * 33 | * @param resource the resource to check 34 | * @return true if the resource should be included 35 | */ 36 | @Override 37 | public boolean accept(Resource resource) 38 | { 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/FilenameEndsWithResourceFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | import java.io.IOException; 20 | 21 | /** 22 | * Accepts only resources where the filename ends with the filter... equivalent to *filter in shell. 23 | * 24 | * @author ypujante@linkedin.com 25 | * 26 | */ 27 | public class FilenameEndsWithResourceFilter implements ResourceFilter 28 | { 29 | private final String _filter; 30 | 31 | /** 32 | * Constructor 33 | */ 34 | public FilenameEndsWithResourceFilter(String filter) 35 | { 36 | _filter = filter; 37 | } 38 | 39 | /** 40 | * Tests whether this resource should be included in the result. 41 | * 42 | * @param resource the resource to check 43 | * @return true if the resource should be included 44 | * @throws IOException 45 | */ 46 | @Override 47 | public boolean accept(Resource resource) 48 | { 49 | return resource.getFilename().endsWith(_filter); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/FilteredResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | import org.linkedin.util.io.resource.internal.AbstractResource; 20 | import org.linkedin.util.io.resource.internal.InternalResourceProvider; 21 | 22 | import java.io.File; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.net.URI; 26 | 27 | /** 28 | * @author ypujante@linkedin.com 29 | * 30 | */ 31 | public class FilteredResource extends AbstractResource 32 | { 33 | private final Resource _resource; 34 | 35 | /** 36 | * Constructor 37 | */ 38 | 39 | public FilteredResource(InternalResourceProvider resourceProvider, 40 | String path, 41 | Resource resource) 42 | { 43 | super(resourceProvider, path); 44 | _resource = resource; 45 | } 46 | 47 | /** 48 | * @return the filtered resource 49 | */ 50 | public Resource getFilteredResource() 51 | { 52 | return _resource; 53 | } 54 | 55 | /** 56 | * @return true if the resource exists. 57 | */ 58 | @Override 59 | public boolean exists() 60 | { 61 | return _resource.exists(); 62 | } 63 | 64 | /** 65 | * Returns a File handle for this resource. 66 | * 67 | * @throws IOException if the resource cannot be resolved as a File handle, i.e. it 68 | * is not available on the file system (or it cannot be made available). 69 | */ 70 | @Override 71 | public File getFile() throws IOException 72 | { 73 | return _resource.getFile(); 74 | } 75 | 76 | /** 77 | * Efficiently returns all information about the resource. 78 | * 79 | * @return information about this resource. 80 | * @throws IOException if cannot get information 81 | */ 82 | @Override 83 | public ResourceInfo getInfo() throws IOException 84 | { 85 | return _resource.getInfo(); 86 | } 87 | 88 | /** 89 | * Important note: the caller of this method is responsible for properly closing the input 90 | * stream! 91 | * 92 | * @return an input stream to the resource. 93 | * @throws IOException if cannot get an input stream 94 | */ 95 | @Override 96 | public InputStream getInputStream() throws IOException 97 | { 98 | return _resource.getInputStream(); 99 | } 100 | 101 | /** 102 | * @return true if this resource represents a directory. 103 | */ 104 | @Override 105 | public boolean isDirectory() 106 | { 107 | return _resource.isDirectory(); 108 | } 109 | 110 | /** 111 | * @return a uri representation of the resource 112 | */ 113 | @Override 114 | public URI toURI() 115 | { 116 | return _resource.toURI(); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/NullResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | import org.linkedin.util.io.resource.internal.AbstractResource; 20 | import org.linkedin.util.io.resource.internal.InternalResourceProvider; 21 | import org.linkedin.util.io.resource.internal.NullResourceProvider; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.net.URI; 27 | import java.net.URISyntaxException; 28 | 29 | /** 30 | * Implements the null pattern for resource (does not exist) 31 | * @author ypujante@linkedin.com 32 | */ 33 | public class NullResource extends AbstractResource 34 | { 35 | public static final NullResource INSTANCE = create(); 36 | 37 | public static NullResource instance() 38 | { 39 | return INSTANCE; 40 | } 41 | 42 | public static class NullResourceException extends IOException 43 | { 44 | private static final long serialVersionUID = 1L; 45 | 46 | public NullResourceException(String s) 47 | { 48 | super(s); 49 | } 50 | } 51 | 52 | private final URI _uri; 53 | 54 | /** 55 | * Constructor 56 | */ 57 | public NullResource(InternalResourceProvider resourceProvider, String path, String fullPath) 58 | { 59 | super(resourceProvider, path); 60 | try 61 | { 62 | _uri = new URI("nullResource:" + fullPath); 63 | } 64 | catch(URISyntaxException e) 65 | { 66 | // should not happen 67 | throw new RuntimeException(e); 68 | } 69 | } 70 | 71 | 72 | /** 73 | * @return true if the resource exists. 74 | */ 75 | @Override 76 | public boolean exists() 77 | { 78 | return false; 79 | } 80 | 81 | /** 82 | * Returns a File handle for this resource. 83 | * 84 | * @throws IOException if the resource cannot be resolved as a File handle, i.e. it 85 | * is not available on the file system (or it cannot be made available). 86 | */ 87 | @Override 88 | public File getFile() throws IOException 89 | { 90 | throw new IOException("not supported"); 91 | } 92 | 93 | 94 | /** 95 | * Important note: the caller of this method is responsible for properly closing the input 96 | * stream! 97 | * 98 | * @return an input stream to the resource. 99 | * @throws IOException if cannot get an input stream 100 | */ 101 | @Override 102 | public InputStream getInputStream() throws IOException 103 | { 104 | throw new NullResourceException(toURI().toString()); 105 | } 106 | 107 | 108 | /** 109 | * Efficiently returns all information about the resource. 110 | * 111 | * @return information about this resource. 112 | * @throws IOException if cannot get information 113 | */ 114 | @Override 115 | public ResourceInfo getInfo() throws IOException 116 | { 117 | throw new NullResourceException(toURI().toString()); 118 | } 119 | 120 | 121 | /** 122 | * @return true if this resource represents a directory. 123 | */ 124 | @Override 125 | public boolean isDirectory() 126 | { 127 | return false; 128 | } 129 | 130 | /** 131 | * @return a uri representation of the resource 132 | */ 133 | @Override 134 | public URI toURI() 135 | { 136 | return _uri; 137 | } 138 | 139 | /** 140 | * Creates a null resource 141 | */ 142 | public static NullResource createFromRoot(String root) 143 | { 144 | return (NullResource) new NullResourceProvider(root).getRootResource(); 145 | } 146 | 147 | /** 148 | * Creates a null resource 149 | */ 150 | public static NullResource create() 151 | { 152 | return createFromRoot("/"); 153 | } 154 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/ResourceFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | /** 20 | * The filter for resources. 21 | * 22 | * @author ypujante@linkedin.com 23 | * 24 | */ 25 | public interface ResourceFilter 26 | { 27 | /** 28 | * Tests whether this resource should be included in the result. 29 | * 30 | * @param resource the resource to check 31 | * @return true if the resource should be included 32 | */ 33 | boolean accept(Resource resource); 34 | } 35 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/ResourceInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | import java.io.IOException; 20 | 21 | /** 22 | * Information about the resource 23 | */ 24 | public interface ResourceInfo 25 | { 26 | /** 27 | * @return the last modified date of this resource 28 | * @throws IOException if there is an io problem 29 | */ 30 | long getLastModified() throws IOException; 31 | 32 | /** 33 | * @return the length of the resource: the number of bytes that will be read when using the 34 | * input stream 35 | * @throws IOException if there is an io problem 36 | */ 37 | long getContentLength() throws IOException; 38 | } 39 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | import java.io.FileNotFoundException; 20 | import java.net.URI; 21 | 22 | /** 23 | * Thrown when a resource is not found. 24 | * 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public class ResourceNotFoundException extends FileNotFoundException 29 | { 30 | private static final long serialVersionUID = 1L; 31 | 32 | private final URI _uri; 33 | 34 | public ResourceNotFoundException(URI uri) 35 | { 36 | super(uri.toString()); 37 | _uri = uri; 38 | } 39 | 40 | public ResourceNotFoundException(URI uri, Throwable cause) 41 | { 42 | super(uri.toString()); 43 | _uri = uri; 44 | initCause(cause); 45 | } 46 | 47 | public ResourceNotFoundException(URI uri, String message) 48 | { 49 | super(uri.toString() + ": " + message); 50 | _uri = uri; 51 | } 52 | 53 | public ResourceNotFoundException(URI uri, String message, Throwable cause) 54 | { 55 | super(uri.toString() + ": " + message); 56 | _uri = uri; 57 | initCause(cause); 58 | } 59 | 60 | public URI getURI() 61 | { 62 | return _uri; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/StaticInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | /** 20 | * Static implementation... 21 | * 22 | * @author ypujante@linkedin.com 23 | * 24 | */ 25 | public class StaticInfo implements ResourceInfo 26 | { 27 | private final long _contentLength; 28 | private final long _lastModified; 29 | 30 | public StaticInfo(long contentLength, long lastModified) 31 | { 32 | _contentLength = contentLength; 33 | _lastModified = lastModified; 34 | } 35 | 36 | @Override 37 | public long getContentLength() 38 | { 39 | return _contentLength; 40 | } 41 | 42 | @Override 43 | public long getLastModified() 44 | { 45 | return _lastModified; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/SubDirResourceFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | /** 20 | * Simple filter to check for filter only sub directories... stateless 21 | * 22 | * @author ypujante@linkedin.com 23 | * 24 | */ 25 | public class SubDirResourceFilter implements ResourceFilter 26 | { 27 | public static final SubDirResourceFilter INSTANCE = new SubDirResourceFilter(); 28 | 29 | public static SubDirResourceFilter instance() 30 | { 31 | return INSTANCE; 32 | } 33 | 34 | /** 35 | * Constructor 36 | */ 37 | public SubDirResourceFilter() 38 | { 39 | } 40 | 41 | /** 42 | * Tests whether this resource should be included in the result. 43 | * 44 | * @param resource the resource to check 45 | * @return true if the resource should be included 46 | */ 47 | @Override 48 | public boolean accept(Resource resource) 49 | { 50 | return resource.isDirectory(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/URIResourceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | import org.linkedin.util.io.resource.internal.FileURIResourceFactory; 20 | import org.linkedin.util.io.resource.internal.JarURIResourceFactory; 21 | import org.linkedin.util.io.resource.internal.SchemeURLResourceFactory; 22 | 23 | import java.net.URI; 24 | 25 | /** 26 | * @author ypujante@linkedin.com 27 | * 28 | */ 29 | public interface URIResourceFactory 30 | { 31 | /** 32 | * The default factory to use when not provided (which should be most of the cases) 33 | */ 34 | URIResourceFactory DEFAULT = 35 | new URIResourceFactoryImpl(new FileURIResourceFactory(), 36 | new JarURIResourceFactory(), 37 | new SchemeURLResourceFactory("http"), 38 | new SchemeURLResourceFactory("https"), 39 | new SchemeURLResourceFactory("ftp")); 40 | 41 | /** 42 | * Based on the URI returns the right resource. Here the rootPath is based on the location 43 | * of the resource itself. 44 | * 45 | * @param uri 46 | * @return the resource 47 | */ 48 | Resource createResource(URI uri) throws UnsupportedURIException; 49 | } 50 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/URIResourceFactoryImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | import org.linkedin.util.io.resource.internal.SchemeURIResourceFactory; 20 | 21 | import java.io.File; 22 | import java.net.URI; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | /** 27 | * Basic implementation based on {@link SchemeURIResourceFactory}. 28 | * 29 | * @author ypujante@linkedin.com 30 | * 31 | */ 32 | public class URIResourceFactoryImpl implements URIResourceFactory 33 | { 34 | private final Map _factories = 35 | new HashMap(); 36 | 37 | /** 38 | * Constructor 39 | */ 40 | public URIResourceFactoryImpl(SchemeURIResourceFactory... factories) 41 | { 42 | for(SchemeURIResourceFactory factory : factories) 43 | { 44 | _factories.put(factory.getScheme(), factory); 45 | } 46 | } 47 | 48 | /** 49 | * Based on the URI returns the right resource 50 | * 51 | * @param uri 52 | * @return the resource 53 | * @throws UnsupportedURIException if the uri is not supported by this factory 54 | */ 55 | @Override 56 | public Resource createResource(URI uri) throws UnsupportedURIException 57 | { 58 | if(uri.getScheme() == null) 59 | return FileResource.createFromRoot(new File(uri.getPath())); 60 | 61 | SchemeURIResourceFactory factory = _factories.get(uri.getScheme()); 62 | if(factory == null) 63 | throw new UnsupportedURIException("unsupported scheme " + uri.getScheme()); 64 | 65 | return factory.createResource(uri, this); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/UnsupportedURIException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource; 18 | 19 | /** 20 | * @author ypujante@linkedin.com 21 | * 22 | */ 23 | public class UnsupportedURIException extends Exception 24 | { 25 | private static final long serialVersionUID = 1L; 26 | 27 | public UnsupportedURIException() 28 | { 29 | } 30 | 31 | public UnsupportedURIException(Throwable cause) 32 | { 33 | super(cause); 34 | } 35 | 36 | public UnsupportedURIException(String message) 37 | { 38 | super(message); 39 | } 40 | 41 | public UnsupportedURIException(String message, Throwable cause) 42 | { 43 | super(message, cause); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/FileResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | import org.linkedin.util.io.resource.FileResource; 22 | import org.linkedin.util.io.resource.ResourceFilter; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | 27 | /** 28 | * @author ypujante@linkedin.com 29 | * 30 | */ 31 | public class FileResourceProvider extends AbstractResourceProvider 32 | { 33 | public static final String MODULE = FileResourceProvider.class.getName(); 34 | public static final Logger log = LoggerFactory.getLogger(MODULE); 35 | 36 | private final File _root; 37 | 38 | /** 39 | * Constructor 40 | */ 41 | public FileResourceProvider(File root) throws IOException 42 | { 43 | _root = root.getCanonicalFile(); 44 | } 45 | 46 | /** 47 | * Builds a resource given a path. Only subclasses know how to do that. 48 | * 49 | * @param path the path to the new resource (always starts with /) 50 | * @return the resource 51 | */ 52 | @Override 53 | public InternalResource doBuildResource(String path) 54 | { 55 | return new FileResource(this, path, new File(_root, path)); 56 | } 57 | 58 | 59 | /** 60 | * Creates a new resource provider given the new path. 61 | * 62 | * @param rootPath 63 | * @return the new resource provider 64 | */ 65 | @Override 66 | public InternalResourceProvider doCreateResourceProvider(String rootPath) 67 | { 68 | try 69 | { 70 | return new FileResourceProvider(new File(_root, rootPath)); 71 | } 72 | catch(IOException e) 73 | { 74 | throw new RuntimeException(e); 75 | } 76 | } 77 | 78 | /** 79 | * If the path denotes a directory, then it will return all resources that are contained in the 80 | * directory. 81 | * 82 | * @param path the path to the resource 83 | * @param filter the filter to include only some resources in the result 84 | * @return true if it was a directory, false otherwise 85 | */ 86 | @Override 87 | public boolean doList(String path, ResourceFilter filter) 88 | { 89 | File file = null; 90 | try 91 | { 92 | file = new File(_root, path).getCanonicalFile(); 93 | } 94 | catch(IOException e) 95 | { 96 | if(log.isDebugEnabled()) 97 | log.debug("exception (ignored) while converting canonical file " + new File(_root, path), e); 98 | 99 | return false; 100 | } 101 | 102 | if(!file.isDirectory()) 103 | return false; 104 | 105 | File[] files = file.listFiles(); 106 | 107 | for(File f : files) 108 | { 109 | filter.accept(new FileResource(this, path + f.getName(), f)); 110 | } 111 | 112 | return true; 113 | } 114 | 115 | @Override 116 | public boolean equals(Object o) 117 | { 118 | if(this == o) return true; 119 | if(o == null || getClass() != o.getClass()) return false; 120 | 121 | FileResourceProvider that = (FileResourceProvider) o; 122 | 123 | if(!_root.equals(that._root)) return false; 124 | 125 | return true; 126 | } 127 | 128 | @Override 129 | public int hashCode() 130 | { 131 | return _root.hashCode(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/FileURIResourceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.FileResource; 20 | import org.linkedin.util.io.resource.Resource; 21 | import org.linkedin.util.io.resource.URIResourceFactory; 22 | 23 | import java.io.File; 24 | import java.net.URI; 25 | 26 | /** 27 | * @author ypujante@linkedin.com 28 | * 29 | */ 30 | public class FileURIResourceFactory extends SchemeURIResourceFactory 31 | { 32 | /** 33 | * Constructor 34 | */ 35 | public FileURIResourceFactory() 36 | { 37 | } 38 | 39 | /** 40 | * @return the protocol that this factory handles 41 | */ 42 | @Override 43 | public String getScheme() 44 | { 45 | return "file"; 46 | } 47 | 48 | 49 | /** 50 | * Method that needs to be implemented by children.. 51 | * 52 | * @param uri 53 | * @param parent the parent resource factory 54 | * @return the resource 55 | */ 56 | @Override 57 | protected Resource doCreateResource(URI uri, URIResourceFactory parent) 58 | { 59 | return FileResource.create(new File("/"), uri.getPath()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/FilteredResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.FilteredResource; 20 | import org.linkedin.util.io.resource.Resource; 21 | import org.linkedin.util.io.resource.ResourceFilter; 22 | 23 | /** 24 | * @author ypujante@linkedin.com 25 | * 26 | */ 27 | public class FilteredResourceProvider extends AbstractResourceProvider 28 | { 29 | private final InternalResourceProvider _resourceProvider; 30 | 31 | /** 32 | * Constructor 33 | */ 34 | public FilteredResourceProvider(InternalResourceProvider resourceProvider) 35 | { 36 | _resourceProvider = resourceProvider; 37 | } 38 | 39 | /** 40 | * Constructor 41 | */ 42 | public FilteredResourceProvider(Resource resource) 43 | { 44 | this((InternalResourceProvider) ((InternalResource) resource).getResourceProvider()); 45 | } 46 | 47 | /** 48 | * @return the filtered resource provider 49 | */ 50 | public InternalResourceProvider getFilteredResourceProvider() 51 | { 52 | return _resourceProvider; 53 | } 54 | 55 | /** 56 | * Builds a resource given a path. Only subclasses know how to do that. 57 | * 58 | * @param path the path to the new resource (always starts with /) 59 | * @return the resource 60 | */ 61 | @Override 62 | public InternalResource doBuildResource(String path) 63 | { 64 | return doBuildResource(_resourceProvider.doBuildResource(path)); 65 | } 66 | 67 | /** 68 | * Creates a new resource provider given the new path. 69 | * 70 | * @param rootPath 71 | * @return the new resource provider 72 | */ 73 | @Override 74 | public InternalResourceProvider doCreateResourceProvider(String rootPath) 75 | { 76 | return doCreateResourceProvider(_resourceProvider.doCreateResourceProvider(rootPath)); 77 | } 78 | 79 | /** 80 | * This method will be implemented by subclasses to create the right kind of resource provider 81 | * 82 | * @param resourceProvider 83 | * @return the resource provider 84 | */ 85 | protected InternalResourceProvider doCreateResourceProvider(InternalResourceProvider resourceProvider) 86 | { 87 | return new FilteredResourceProvider(resourceProvider); 88 | } 89 | 90 | /** 91 | * If the path denotes a directory, then it will return all resources that are contained in the 92 | * directory. 93 | * 94 | * @param path the path to the resource (it already ends with /) 95 | * @param filter the filter to include only some resources in the result 96 | * @return true if it was a directory, false otherwise 97 | */ 98 | @Override 99 | public boolean doList(String path, final ResourceFilter filter) 100 | { 101 | ResourceFilter newFilter = new ResourceFilter() 102 | { 103 | @Override 104 | public boolean accept(Resource resource) 105 | { 106 | return filter.accept(doBuildResource(resource)); 107 | } 108 | }; 109 | 110 | return _resourceProvider.doList(path, newFilter); 111 | } 112 | 113 | /** 114 | * This method will be implemented by subclasses to create the right kind of resource. 115 | * 116 | * @param filteredResource 117 | * @return the resource 118 | */ 119 | protected InternalResource doBuildResource(Resource filteredResource) 120 | { 121 | return new FilteredResource(this, filteredResource.getPath(), filteredResource); 122 | } 123 | 124 | @Override 125 | public boolean equals(Object o) 126 | { 127 | if(this == o) return true; 128 | if(o == null || getClass() != o.getClass()) return false; 129 | 130 | FilteredResourceProvider that = (FilteredResourceProvider) o; 131 | 132 | if(!_resourceProvider.equals(that._resourceProvider)) return false; 133 | 134 | return true; 135 | } 136 | 137 | @Override 138 | public int hashCode() 139 | { 140 | return _resourceProvider.hashCode(); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/InternalResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.Resource; 20 | 21 | /** 22 | * All resources need to implement this internal interface. 23 | * 24 | * @author ypujante@linkedin.com 25 | * 26 | */ 27 | public interface InternalResource extends Resource 28 | { 29 | /** 30 | * @return the resource provider that created this resource 31 | */ 32 | ResourceProvider getResourceProvider(); 33 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/InternalResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.ResourceFilter; 20 | 21 | import java.io.IOException; 22 | 23 | /** 24 | * All resource providers need to implement this internal interface. 25 | * 26 | * @author ypujante@linkedin.com 27 | * 28 | */ 29 | public interface InternalResourceProvider extends ResourceProvider 30 | { 31 | /** 32 | * @param resource 33 | * @return the parent of a resource 34 | */ 35 | InternalResource getParentResource(InternalResource resource); 36 | 37 | /** 38 | * @param resource 39 | * @param relativePath the relative path 40 | * @return a resource relative to the resource 41 | */ 42 | InternalResource createRelative(InternalResource resource, String relativePath); 43 | 44 | /** 45 | * Returns a new resource with the root resource set to this resource. 46 | * 47 | * @return the new resource 48 | */ 49 | InternalResource chroot(InternalResource resource); 50 | 51 | /** 52 | * If this resource denotes a directory, then it will return all resources that are contained 53 | * in the directory. 54 | * 55 | * @param filter the filter to include only some resources in the result 56 | * @return all the resources contained in the directory or null if not a directory 57 | * @throws IOException if there is an error accessing the resource 58 | */ 59 | InternalResource[] list(InternalResource resource, ResourceFilter filter) throws IOException; 60 | 61 | /** 62 | * @return the root resource 63 | */ 64 | InternalResource getRootResource(); 65 | 66 | /** 67 | * Builds a resource given a path. Only subclasses know how to do that. 68 | * 69 | * @param path the path to the new resource (always starts with /) 70 | * @return the resource 71 | */ 72 | InternalResource doBuildResource(String path); 73 | 74 | /** 75 | * If the path denotes a directory, then it will return all resources that are contained in 76 | * the directory. 77 | * 78 | * @param path the path to the resource (it already ends with /) 79 | * @param filter the filter to include only some resources in the result 80 | * @return true if it was a directory, false otherwise 81 | */ 82 | boolean doList(String path, ResourceFilter filter); 83 | 84 | /** 85 | * Creates a new resource provider given the new path. 86 | * 87 | * @param rootPath 88 | * @return the new resource provider 89 | */ 90 | InternalResourceProvider doCreateResourceProvider(String rootPath); 91 | } 92 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/JarURIResourceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.JarResource; 20 | import org.linkedin.util.io.resource.Resource; 21 | import org.linkedin.util.io.resource.URIResourceFactory; 22 | 23 | import java.io.IOException; 24 | import java.net.URI; 25 | import java.net.URISyntaxException; 26 | 27 | /** 28 | * @author ypujante@linkedin.com 29 | * 30 | */ 31 | public class JarURIResourceFactory extends SchemeURIResourceFactory 32 | { 33 | /** 34 | * Constructor 35 | */ 36 | public JarURIResourceFactory() 37 | { 38 | } 39 | 40 | /** 41 | * @return the protocol that this factory handles 42 | */ 43 | @Override 44 | public String getScheme() 45 | { 46 | return "jar"; 47 | } 48 | 49 | /** 50 | * Method that needs to be implemented by children.. 51 | * 52 | * @param uri 53 | * @param parent the parent resource factory 54 | * @return the resource 55 | * @throws IOException if there is a problem creating the resource 56 | */ 57 | @Override 58 | protected Resource doCreateResource(URI uri, URIResourceFactory parent) 59 | { 60 | try 61 | { 62 | return JarResource.create(uri, parent); 63 | } 64 | catch(URISyntaxException e) 65 | { 66 | throw new IllegalArgumentException(uri.toString(), e); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/LeafResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.Resource; 20 | import org.linkedin.util.io.resource.ResourceInfo; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.io.File; 25 | import java.net.URI; 26 | 27 | /** 28 | * Subset of the interface {@link Resource} when we have a leaf (meaning a file). Note that this 29 | * api does not have any 'navigation' features (like createRelative or 30 | * getParentResource). 31 | * 32 | * @author ypujante@linkedin.com 33 | * 34 | */ 35 | public interface LeafResource 36 | { 37 | /** 38 | * @return true if the resource exists. 39 | */ 40 | boolean exists(); 41 | 42 | /** 43 | * Returns a File handle for this resource. 44 | * 45 | * @throws IOException if the resource cannot be resolved as a File handle, i.e. 46 | * it is not available on the file system (or it cannot be made available). 47 | */ 48 | File getFile() throws IOException; 49 | 50 | /** 51 | * Efficiently returns all information about the resource. 52 | * 53 | * @return information about this resource. 54 | * @throws IOException if cannot get information 55 | */ 56 | ResourceInfo getInfo() throws IOException; 57 | 58 | /** 59 | * Shortcut to getInfo().getLastModified() with the same meaning as the 60 | * File.lastModified api: returns 0L if the resource does not 61 | * exist or if an IO error occurs. 62 | * 63 | * @return the last modified date of this resource. 64 | */ 65 | long lastModified(); 66 | 67 | /** 68 | * Returns true if this resource was modified since the time provided. A trivial 69 | * implementation is return lastModified() > time, but various implementations 70 | * can provide better alternatives. If the resource does not exsit then it returns 71 | * false. 72 | * 73 | * @param time the time to check against 74 | * @return a boolean 75 | */ 76 | boolean isModifiedSince(long time); 77 | 78 | /** 79 | * Shortcut to getInfo().getContentLength() with the same meaning as the 80 | * File.length() api: returns 0L if the resource does not 81 | * exist or if an IO error occurs. 82 | * 83 | * @return the length in bytes of the resource. 84 | */ 85 | long length(); 86 | 87 | /** 88 | * @return a uri representation of the resource 89 | */ 90 | URI toURI(); 91 | 92 | /** 93 | * @return the filename portion of this resource. If it is a directory, returns the name of the 94 | * directory. 95 | */ 96 | String getFilename(); 97 | 98 | /** 99 | * @return the path to the resource (within the context of the resource provider) 100 | */ 101 | String getPath(); 102 | 103 | /** 104 | * Important note: the caller of this method is responsible for properly closing the 105 | * input stream! 106 | * 107 | * @return an input stream to the resource. 108 | * @throws IOException if cannot get an input stream 109 | */ 110 | InputStream getInputStream() throws IOException; 111 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/NullResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.PathUtils; 20 | import org.linkedin.util.io.resource.NullResource; 21 | import org.linkedin.util.io.resource.ResourceFilter; 22 | 23 | /** 24 | * Implements the null pattern for resource (does not exist) 25 | * @author ypujante@linkedin.com 26 | */ 27 | public class NullResourceProvider extends PathBasedResourceProvider 28 | { 29 | 30 | 31 | /** 32 | * Constructor 33 | */ 34 | public NullResourceProvider() 35 | { 36 | this("/"); 37 | } 38 | 39 | /** 40 | * Constructor 41 | */ 42 | public NullResourceProvider(String root) 43 | { 44 | super(normalizePath(root)); 45 | } 46 | 47 | /** 48 | * Builds a resource given a path. Only subclasses know how to do that. 49 | * 50 | * @param path the path to the new resource (always starts with /) 51 | * @return the resource 52 | */ 53 | @Override 54 | public InternalResource doBuildResource(String path) 55 | { 56 | return new NullResource(this, normalizePath(path), normalizePath(getFullPath(path))); 57 | } 58 | 59 | /** 60 | * The path never represents a directory => should not end with / 61 | */ 62 | private static String normalizePath(String path) 63 | { 64 | path = PathUtils.removeTrailingSlash(path); 65 | path = PathUtils.addLeadingSlash(path); 66 | return path; 67 | } 68 | 69 | /** 70 | * Creates a new resource provider given the new path. 71 | * 72 | * @param rootPath 73 | * @return the new resource provider 74 | */ 75 | @Override 76 | public InternalResourceProvider doCreateResourceProvider(String rootPath) 77 | { 78 | return new NullResourceProvider(getFullPath(rootPath)); 79 | } 80 | 81 | /** 82 | * If the path denotes a directory, then it will return all resources that are contained in the 83 | * directory. 84 | * 85 | * @param path the path to the resource 86 | * @param filter the filter to include only some resources in the result 87 | * @return true if it was a directory, false otherwise 88 | */ 89 | @Override 90 | public boolean doList(String path, ResourceFilter filter) 91 | { 92 | return false; 93 | } 94 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/PathBasedResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.PathUtils; 20 | 21 | import java.net.URI; 22 | 23 | /** 24 | * Case were there is a root path... 25 | * 26 | * @author ypujante@linkedin.com 27 | * 28 | */ 29 | public abstract class PathBasedResourceProvider extends AbstractResourceProvider 30 | { 31 | private final String _root; 32 | 33 | /** 34 | * Constructor 35 | */ 36 | public PathBasedResourceProvider(String root) 37 | { 38 | root = URI.create(root).normalize().getPath(); 39 | _root = PathUtils.addLeadingSlash(root); 40 | } 41 | 42 | protected String getFullPath(String path) 43 | { 44 | return PathUtils.addPaths(_root, path); 45 | } 46 | 47 | protected String getRelativePath(String fullPath) 48 | { 49 | return PathUtils.addLeadingSlash(fullPath.substring(_root.length())); 50 | } 51 | 52 | public String getRoot() 53 | { 54 | return _root; 55 | } 56 | 57 | @Override 58 | public boolean equals(Object o) 59 | { 60 | if(this == o) return true; 61 | if(o == null || getClass() != o.getClass()) return false; 62 | 63 | PathBasedResourceProvider that = (PathBasedResourceProvider) o; 64 | 65 | if(!_root.equals(that._root)) return false; 66 | 67 | return true; 68 | } 69 | 70 | @Override 71 | public int hashCode() 72 | { 73 | return _root.hashCode(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/RAMResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.PathUtils; 20 | import org.linkedin.util.io.ram.RAMDirectory; 21 | import org.linkedin.util.io.ram.RAMEntry; 22 | import org.linkedin.util.io.resource.RAMResource; 23 | import org.linkedin.util.io.resource.ResourceFilter; 24 | 25 | import java.io.IOException; 26 | 27 | /** 28 | * @author ypujante@linkedin.com 29 | * 30 | */ 31 | public class RAMResourceProvider extends PathBasedResourceProvider 32 | { 33 | private final RAMDirectory _root; 34 | 35 | /** 36 | * Constructor 37 | */ 38 | public RAMResourceProvider(RAMDirectory root) 39 | { 40 | this(root, "/"); 41 | } 42 | 43 | /** 44 | * Constructor 45 | */ 46 | public RAMResourceProvider(RAMDirectory root, String rootPath) 47 | { 48 | super(rootPath); 49 | _root = root; 50 | } 51 | 52 | /** 53 | * Builds a resource given a path. Only subclasses know how to do that. 54 | * 55 | * @param path the path to the new resource (always starts with /) 56 | * @return the resource 57 | */ 58 | @Override 59 | public InternalResource doBuildResource(String path) 60 | { 61 | return new RAMResource(this, getFullPath(path), path); 62 | } 63 | 64 | /** 65 | * Creates a new resource provider given the new path. 66 | * 67 | * @param rootPath 68 | * @return the new resource provider 69 | */ 70 | @Override 71 | public InternalResourceProvider doCreateResourceProvider(String rootPath) 72 | { 73 | return new RAMResourceProvider(_root, getFullPath(rootPath)); 74 | } 75 | 76 | /** 77 | * If the path denotes a directory, then it will return all resources that are contained in the 78 | * directory. 79 | * 80 | * @param path the path to the resource 81 | * @param filter the filter to include only some resources in the result 82 | * @return true if it was a directory, false otherwise 83 | * @throws IOException if there is an error accessing the resource 84 | */ 85 | @Override 86 | public boolean doList(String path, ResourceFilter filter) 87 | { 88 | if(_root == null) 89 | return false; 90 | 91 | RAMEntry entry = _root.getEntryByPath(path); 92 | 93 | if(entry instanceof RAMDirectory) 94 | { 95 | RAMDirectory ramDirectory = (RAMDirectory) entry; 96 | for(RAMEntry ramEntry : ramDirectory.ls()) 97 | { 98 | String resourcePath = PathUtils.addPaths(path, ramEntry.name()); 99 | filter.accept(new RAMResource(this, 100 | getFullPath(resourcePath), 101 | resourcePath)); 102 | } 103 | return true; 104 | } 105 | else 106 | return false; 107 | } 108 | 109 | public RAMEntry getRAMEntry(String fullpath) 110 | { 111 | return _root.getEntryByPath(fullpath); 112 | } 113 | 114 | @Override 115 | public boolean equals(Object o) 116 | { 117 | if(this == o) return true; 118 | if(o == null || getClass() != o.getClass()) return false; 119 | if(!super.equals(o)) return false; 120 | 121 | RAMResourceProvider that = (RAMResourceProvider) o; 122 | 123 | if(_root != null ? !_root.equals(that._root) : that._root != null) return false; 124 | 125 | return true; 126 | } 127 | 128 | @Override 129 | public int hashCode() 130 | { 131 | int result = super.hashCode(); 132 | result = 31 * result + (_root != null ? _root.hashCode() : 0); 133 | return result; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/ResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.Resource; 20 | 21 | /** 22 | * This is the base notion of a provider of resources. There will be different implementation 23 | * depending on the type of resource that needs to be returned. 24 | * 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public interface ResourceProvider 29 | { 30 | /** 31 | * The path to the resource is absolute. Whether it starts with / or not it will be made 32 | * absolute. 33 | * 34 | * Note that it follows the same convention as {@link java.io.File} class in the sense 35 | * that a resource simply represent a handle and does not imply that the resource exists. 36 | * 37 | * @param path the path to the resource 38 | * @return the resource given the path 39 | */ 40 | Resource createResource(String path); 41 | } 42 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/SchemeURIResourceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.Resource; 20 | import org.linkedin.util.io.resource.URIResourceFactory; 21 | 22 | import java.net.URI; 23 | 24 | /** 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public abstract class SchemeURIResourceFactory 29 | { 30 | /** 31 | * Constructor 32 | */ 33 | public SchemeURIResourceFactory() 34 | { 35 | } 36 | 37 | /** 38 | * @return the scheme that this factory handles 39 | */ 40 | public abstract String getScheme(); 41 | 42 | 43 | /** 44 | * Based on the URI returns the right resource 45 | * 46 | * @param uri 47 | * @return the resource 48 | */ 49 | public Resource createResource(URI uri, URIResourceFactory parent) 50 | { 51 | if(!getScheme().equals(uri.getScheme())) 52 | throw new IllegalArgumentException("cannot handle: " + uri.getScheme()); 53 | 54 | return doCreateResource(uri, parent); 55 | } 56 | 57 | /** 58 | * Method that needs to be implemented by children.. 59 | * 60 | * @param uri 61 | * @param parent the parent resource factory 62 | * @return the resource 63 | */ 64 | protected abstract Resource doCreateResource(URI uri, URIResourceFactory parent); 65 | } 66 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/SchemeURLResourceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.io.resource.internal; 18 | 19 | import org.linkedin.util.io.resource.Resource; 20 | import org.linkedin.util.io.resource.URIResourceFactory; 21 | import org.linkedin.util.io.resource.URLResource; 22 | 23 | import java.net.MalformedURLException; 24 | import java.net.URI; 25 | 26 | /** 27 | * Handles generic URL.. the scheme is provided. (ex: http, ftp...) 28 | * 29 | * @author ypujante@linkedin.com 30 | * 31 | */ 32 | public class SchemeURLResourceFactory extends SchemeURIResourceFactory 33 | { 34 | private final String _scheme; 35 | 36 | /** 37 | * Constructor 38 | */ 39 | public SchemeURLResourceFactory(String scheme) 40 | { 41 | _scheme = scheme; 42 | } 43 | 44 | /** 45 | * @return the scheme that this factory handles 46 | */ 47 | @Override 48 | public String getScheme() 49 | { 50 | return _scheme; 51 | } 52 | 53 | 54 | /** 55 | * Method that needs to be implemented by children.. 56 | * 57 | * @param uri 58 | * @param parent the parent resource factory 59 | * @return the resource 60 | */ 61 | @Override 62 | protected Resource doCreateResource(URI uri, URIResourceFactory parent) 63 | { 64 | try 65 | { 66 | return URLResource.createFromRoot(uri.toURL()); 67 | } 68 | catch(MalformedURLException e) 69 | { 70 | throw new IllegalArgumentException(uri.toString(), e); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/CannotConfigureException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | import org.linkedin.util.exceptions.InternalException; 20 | 21 | /** 22 | * @author ypujante@linkedin.com */ 23 | public class CannotConfigureException extends InternalException 24 | { 25 | private static final long serialVersionUID = 1L; 26 | 27 | public CannotConfigureException() 28 | { 29 | } 30 | 31 | public CannotConfigureException(String s) 32 | { 33 | super(s); 34 | } 35 | 36 | public CannotConfigureException(Throwable th) 37 | { 38 | super(th); 39 | } 40 | 41 | public CannotConfigureException(String s, Throwable throwable) 42 | { 43 | super(s, throwable); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Configurable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * @author ypujante@linkedin.com */ 23 | public interface Configurable 24 | { 25 | void configure(Map config); 26 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Destroyable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | /** 20 | * This interface defines the API of an entity that is destroyable. The main 21 | * difference between Destroyable and Shutdownable 22 | * is that for the entity there is nothing to wait for (in other words all the 23 | * calls to the entity are blocking calls). It is also possible to have an 24 | * entity that implements both Destroyable and 25 | * Shutdownable in which case, the proper way would be: 26 | * 27 | *
28 |  *   entity.shutdown();
29 |  *   entity.waitForShutdown();
30 |  *   // here we know that all the non blocking calls are terminated
31 |  *   entity.destroy();
32 |  * 
33 | * 34 | * @author ypujante@linkedin.com 35 | * @see Shutdownable */ 36 | public interface Destroyable extends Terminable 37 | { 38 | /** 39 | * This method destroys the entity, cleaning up any resource that needs to 40 | * be cleaned up, like closing files, database connection.. */ 41 | public void destroy(); 42 | } 43 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Shutdown.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | import org.linkedin.util.annotations.Initializable; 20 | import org.linkedin.util.clock.Timespan; 21 | import org.linkedin.util.concurrent.WaitableCounter; 22 | 23 | import java.io.Serializable; 24 | import java.util.concurrent.TimeoutException; 25 | 26 | /** 27 | * Simple object that has the knowledge wether we are in shutdown or not. Works in close relation 28 | * with {@link ShutdownProxy}. 29 | * 30 | * @author ypujante@linkedin.com 31 | * 32 | */ 33 | public class Shutdown implements Serializable, Shutdownable 34 | { 35 | private static final long serialVersionUID = 1L; 36 | 37 | private boolean _shutdown = false; 38 | 39 | @Initializable 40 | public WaitableCounter pendingCallsCount = new WaitableCounter(); 41 | 42 | @Initializable 43 | public String module = Shutdown.class.getName(); 44 | 45 | /** 46 | * Constructor 47 | */ 48 | public Shutdown() 49 | { 50 | } 51 | 52 | /** 53 | * Sets the system is shutdown */ 54 | @Override 55 | public synchronized void shutdown() 56 | { 57 | _shutdown = true; 58 | } 59 | 60 | /** 61 | * Waits for shutdown to be completed. After calling shutdown, there may still be some pending 62 | * work that needs to be accomplised. This method will block until it is done. 63 | * 64 | * @throws InterruptedException if interrupted while waiting 65 | * @throws IllegalStateException if shutdown has not been called 66 | */ 67 | @Override 68 | public void waitForShutdown() throws InterruptedException, IllegalStateException 69 | { 70 | if(!_shutdown) throw new IllegalStateException("call shutdown first"); 71 | pendingCallsCount.waitForCounter(); 72 | } 73 | 74 | /** 75 | * Waits for shutdown to be completed. After calling shutdown, there may still be some pending work 76 | * that needs to be accomplised. This method will block until it is done but no longer than the 77 | * timeout. 78 | * 79 | * @param timeout how long to wait maximum for the shutdown 80 | * @throws InterruptedException if interrupted while waiting 81 | * @throws IllegalStateException if shutdown has not been called 82 | * @throws TimeoutException if shutdown still not complete after timeout 83 | */ 84 | @Override 85 | public void waitForShutdown(Object timeout) 86 | throws InterruptedException, IllegalStateException, TimeoutException 87 | { 88 | if(!_shutdown) throw new IllegalStateException("call shutdown first"); 89 | pendingCallsCount.waitForCounter(timeout); 90 | } 91 | 92 | /** 93 | * Called right before executing a call 94 | * 95 | * @throws ShutdownRequestedException 96 | */ 97 | synchronized void startCall() throws ShutdownRequestedException 98 | { 99 | if(_shutdown) 100 | throw new ShutdownRequestedException(module); 101 | 102 | pendingCallsCount.inc(); 103 | } 104 | 105 | /** 106 | * MUST be called if {@link #startCall()} is called after the call (typically in a 107 | * finally) 108 | */ 109 | void endCall() 110 | { 111 | pendingCallsCount.dec(); 112 | } 113 | 114 | /** 115 | * @return the number of currently pending calls 116 | */ 117 | public int getPendingCallsCount() 118 | { 119 | return pendingCallsCount.getCounter(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/ShutdownRequestedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | import org.linkedin.util.exceptions.InternalException; 20 | 21 | /** 22 | * Thrown when shutdown has been requested. As a result the method cannot 23 | * be executed. 24 | * 25 | * @author ypujante@linkedin.com 26 | */ 27 | public class ShutdownRequestedException extends InternalException 28 | { 29 | private static final long serialVersionUID = 1L; 30 | 31 | /** 32 | * Constructor */ 33 | public ShutdownRequestedException(String module) 34 | { 35 | super(module); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Shutdownable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | import org.linkedin.util.clock.ClockUtils; 20 | import org.linkedin.util.clock.Timespan; 21 | 22 | import java.util.concurrent.TimeoutException; 23 | 24 | /** 25 | * Defines the method of an entity that is shutdownable 26 | * 27 | * @author ypujante@linkedin.com */ 28 | public interface Shutdownable extends Terminable 29 | { 30 | /** 31 | * This methods sets the entity in shutdown mode. Any method call on this 32 | * entity after shutdown should be either rejected 33 | * (IllegalStateException) or discarded. This method should 34 | * not block and return immediately. 35 | * 36 | * @see #waitForShutdown() */ 37 | public void shutdown(); 38 | 39 | /** 40 | * Waits for shutdown to be completed. After calling shutdown, there may 41 | * still be some pending work that needs to be accomplised. This method 42 | * will block until it is done. 43 | * 44 | * @exception InterruptedException if interrupted while waiting 45 | * @exception IllegalStateException if shutdown has not been called */ 46 | public void waitForShutdown() 47 | throws InterruptedException, IllegalStateException; 48 | 49 | /** 50 | * Waits for shutdown to be completed. After calling shutdown, there may 51 | * still be some pending work that needs to be accomplised. This method 52 | * will block until it is done but no longer than the timeout. 53 | * 54 | * @param timeout how long to wait maximum for the shutdown 55 | * (see {@link ClockUtils#toTimespan(Object)}) 56 | * @exception InterruptedException if interrupted while waiting 57 | * @exception IllegalStateException if shutdown has not been called 58 | * @exception TimeoutException if shutdown still not complete after timeout */ 59 | public void waitForShutdown(Object timeout) 60 | throws InterruptedException, IllegalStateException, TimeoutException; 61 | } 62 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Startable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | /** 20 | * Defines an entity that can be started. 21 | * 22 | * @author ypujante@linkedin.com 23 | * 24 | */ 25 | public interface Startable 26 | { 27 | /** 28 | * This method must NOT block and should start the entity and return right away. 29 | */ 30 | void start(); 31 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Terminable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.lifecycle; 18 | 19 | /** 20 | * This is simply a marker interface that defines the fact that an entity can 21 | * be terminated (shutdown, destroy) 22 | * 23 | * @author ypujante@linkedin.com */ 24 | public interface Terminable 25 | { 26 | } 27 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/NullClassLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.reflect; 19 | 20 | import java.net.URL; 21 | 22 | /** 23 | * Null pattern for class loader... 24 | * 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public class NullClassLoader extends ClassLoader 29 | { 30 | public static final NullClassLoader INSTANCE = new NullClassLoader(); 31 | 32 | public static NullClassLoader instance() 33 | { 34 | return INSTANCE; 35 | } 36 | 37 | /** 38 | * Constructor 39 | */ 40 | public NullClassLoader() 41 | { 42 | } 43 | 44 | @Override 45 | public Class loadClass(String name) throws ClassNotFoundException 46 | { 47 | throw new ClassNotFoundException(name); 48 | } 49 | 50 | @Override 51 | public URL getResource(String name) 52 | { 53 | return null; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/ObjectProxy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.reflect; 18 | 19 | /** 20 | * This interface represents an object proxied. It will most likely be implemented by invocation 21 | * handlers when using dynamic proxy. The concept of {@link java.lang.reflect.Proxy} does not 22 | * necessarily represent a proxy over an object. This interface is meant to specify this restriction 23 | * which is 99% of the cases in which we use dynamic proxies! 24 | * 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public interface ObjectProxy 29 | { 30 | /** 31 | * @return the object proxied */ 32 | T getProxiedObject(); 33 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/ObjectProxyBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.reflect; 19 | 20 | 21 | import java.lang.reflect.InvocationHandler; 22 | import java.lang.reflect.Proxy; 23 | import java.util.ArrayList; 24 | import java.util.Collection; 25 | import java.util.List; 26 | 27 | /** 28 | * @author ypujante@linkedin.com 29 | * 30 | */ 31 | public class ObjectProxyBuilder 32 | { 33 | /** 34 | * Convenient call which creates a proxy using the handler and the interface. It will also 35 | * check that the object bien proxied (if implements ObjectProxy) properly 36 | * implement the interface... 37 | * 38 | * @return the proxy (which implement all the interface) 39 | */ 40 | @SuppressWarnings("unchecked") 41 | public static T createProxy(InvocationHandler handler, Class itface) 42 | { 43 | if(handler instanceof ObjectProxy) 44 | { 45 | ObjectProxy proxy = (ObjectProxy) handler; 46 | if(!ReflectUtils.isSubClassOrInterfaceOf(proxy.getProxiedObject().getClass(), itface)) 47 | throw new IllegalArgumentException(proxy.getProxiedObject().getClass() + " does not extend " + itface); 48 | } 49 | 50 | return (T) Proxy.newProxyInstance(itface.getClassLoader(), 51 | new Class[] {itface}, 52 | handler); 53 | } 54 | 55 | /** 56 | * Convenient call which creates a proxy using the handler and the interfaces. It will also 57 | * check that the object bien proxied (if implements ObjectProxy) properly 58 | * implement the right interfaces... 59 | * 60 | * @return the proxy (which implement all the provided interfaces) 61 | */ 62 | public static Object createProxy(InvocationHandler handler, Class... itfaces) 63 | { 64 | if(handler instanceof ObjectProxy) 65 | { 66 | ObjectProxy proxy = (ObjectProxy) handler; 67 | Class proxyClass = proxy.getProxiedObject().getClass(); 68 | for(Class itface : itfaces) 69 | { 70 | if(!ReflectUtils.isSubClassOrInterfaceOf(proxyClass, itface)) 71 | throw new IllegalArgumentException(proxyClass + " does not extend " + itface); 72 | } 73 | } 74 | 75 | List classLoaders = new ArrayList(); 76 | for(Class itface : itfaces) 77 | { 78 | classLoaders.add(itface.getClassLoader()); 79 | } 80 | 81 | ClassLoader classLoader = ClassLoaderChain.createChain(classLoaders); 82 | 83 | return Proxy.newProxyInstance(classLoader, 84 | itfaces, 85 | handler); 86 | } 87 | 88 | /** 89 | * @see #createProxy(InvocationHandler, Class[]) 90 | */ 91 | public static Object createProxy(InvocationHandler handler, Collection> interfaces) 92 | { 93 | return createProxy(handler, interfaces.toArray(new Class[interfaces.size()])); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/ObjectProxyInvocationHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.reflect; 18 | 19 | import java.lang.reflect.InvocationHandler; 20 | import java.lang.reflect.Proxy; 21 | import java.lang.reflect.Method; 22 | import java.lang.reflect.InvocationTargetException; 23 | 24 | /** 25 | * Very basic implementation of the proxy which simply delegates all calls to the proxied object. 26 | * 27 | * @author ypujante@linkedin.com 28 | * 29 | */ 30 | public class ObjectProxyInvocationHandler implements ObjectProxy, InvocationHandler 31 | { 32 | private final T _proxiedObject; 33 | 34 | /** 35 | * Constructor 36 | */ 37 | public ObjectProxyInvocationHandler(T proxiedObject) 38 | { 39 | _proxiedObject = proxiedObject; 40 | } 41 | 42 | /** 43 | * @return the object proxied 44 | */ 45 | @Override 46 | public T getProxiedObject() 47 | { 48 | return _proxiedObject; 49 | } 50 | 51 | @Override 52 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 53 | { 54 | try 55 | { 56 | return method.invoke(_proxiedObject, args); 57 | } 58 | catch(InvocationTargetException e) 59 | { 60 | throw e.getTargetException(); 61 | } 62 | } 63 | 64 | /** 65 | * This is a convenient call when you want to proxy an object with the unique given 66 | * interface. Note that you can use the more general call {@link Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)} 67 | * if you want to do something different. 68 | * 69 | * @param interfaceToProxy the interface to proxy 70 | * @param objectToProxy the object to proxy (note that it must implement interfaceToProxy!) 71 | * @return the proxied object */ 72 | @SuppressWarnings("unchecked") 73 | public static T createProxy(Class interfaceToProxy, T objectToProxy) 74 | { 75 | // since there is only one interface in the array, we know that the proxy must implement it! 76 | return (T) Proxy.newProxyInstance(interfaceToProxy.getClassLoader(), 77 | new Class[] {interfaceToProxy}, 78 | new ObjectProxyInvocationHandler(objectToProxy)); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/text/IdentityString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.text; 18 | 19 | import org.linkedin.util.reflect.ObjectProxy; 20 | 21 | import java.lang.reflect.Array; 22 | import java.lang.reflect.Proxy; 23 | import java.lang.reflect.InvocationHandler; 24 | 25 | /** 26 | * @author ypujante@linkedin.com 27 | * 28 | */ 29 | public class IdentityString 30 | { 31 | public final static IdentityString FULL_IDENTITY_STRING = 32 | new IdentityString(new ClassNameExtractor() 33 | { 34 | @Override 35 | public String getClassName(Object o) 36 | { 37 | return o.getClass().getName(); 38 | } 39 | }); 40 | 41 | public final static IdentityString SHORT_IDENTITY_STRING = 42 | new IdentityString(new ClassNameExtractor() 43 | { 44 | @Override 45 | public String getClassName(Object o) 46 | { 47 | return o.getClass().getSimpleName(); 48 | } 49 | }); 50 | 51 | private static interface ClassNameExtractor 52 | { 53 | String getClassName(Object o); 54 | } 55 | 56 | private final ClassNameExtractor _classNameExtractor; 57 | 58 | /** 59 | * Constructor 60 | */ 61 | public IdentityString(ClassNameExtractor classNameExtractor) 62 | { 63 | _classNameExtractor = classNameExtractor; 64 | } 65 | 66 | public String getIdentity(Object o) 67 | { 68 | if(o == null) 69 | return "null"; 70 | 71 | if(o.getClass().isArray()) 72 | { 73 | int len = Array.getLength(o); 74 | StringBuilder sb = new StringBuilder(); 75 | for(int i = 0; i < len; i++) 76 | { 77 | if(i > 0) 78 | sb.append(","); 79 | sb.append(getIdentity(Array.get(o, i))); 80 | } 81 | return sb.toString(); 82 | } 83 | 84 | StringBuilder sb = new StringBuilder(); 85 | 86 | sb.append(_classNameExtractor.getClassName(o)).append('@').append(Integer.toHexString(System.identityHashCode(o))); 87 | 88 | if(Proxy.isProxyClass(o.getClass())) 89 | { 90 | InvocationHandler invocationHandler = Proxy.getInvocationHandler(o); 91 | if(invocationHandler instanceof ObjectProxy) 92 | { 93 | ObjectProxy objectProxy = (ObjectProxy) invocationHandler; 94 | Object proxiedObject = objectProxy.getProxiedObject(); 95 | 96 | sb.append(" (proxy of: ").append(getIdentity(proxiedObject)).append(")"); 97 | } 98 | } 99 | 100 | return sb.toString(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/text/TextUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.text; 19 | 20 | /** 21 | * @author ypujante@linkedin.com 22 | * 23 | */ 24 | public class TextUtils 25 | { 26 | 27 | /** 28 | * @param s the string to test 29 | * @return true iff s is null or if s contains only whitespace. 30 | */ 31 | public static boolean isEmptyString(String s) 32 | { 33 | return s == null || s.trim().length() == 0; 34 | } 35 | 36 | /** 37 | * Searches in the string 's' all occurences of the 38 | * substring 'src' and replaces it with the string 39 | * 'dst'. 40 | * 41 | * @param s the string to search 42 | * @param src the substring to search for inside s 43 | * @param dst the replacing string 44 | * @return the string with the text replaced */ 45 | public static String searchAndReplace(String s, String src, String dst) 46 | { 47 | if(s == null) 48 | return null; 49 | 50 | StringBuilder result = new StringBuilder(); 51 | 52 | int i = 0; 53 | int len = s.length(); 54 | int len2 = src.length(); 55 | 56 | while(i < len) 57 | { 58 | int index = s.indexOf(src, i); 59 | if(index == -1) 60 | { 61 | if(i == 0) 62 | return s; 63 | 64 | result.append(s.substring(i)); 65 | break; 66 | } 67 | 68 | result.append(s.substring(i, index)); 69 | result.append(dst); 70 | 71 | i = index + len2; 72 | } 73 | 74 | return result.toString(); 75 | } 76 | 77 | /** 78 | * Constructor 79 | */ 80 | private TextUtils() 81 | { 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/url/FilteredURL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.url; 18 | 19 | import java.io.Serializable; 20 | import java.util.List; 21 | 22 | /** 23 | * Simple filter on URL 24 | * 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public class FilteredURL implements URL, Serializable 29 | { 30 | private final static long serialVersionUID = 1L; 31 | private final URL _urlToFilter; 32 | 33 | /** 34 | * Constructor 35 | */ 36 | public FilteredURL(URL urlToFilter) 37 | { 38 | _urlToFilter = urlToFilter; 39 | } 40 | 41 | public URL getFilteredURL() 42 | { 43 | return _urlToFilter; 44 | } 45 | 46 | @Override 47 | public URL createRelativeURL() 48 | { 49 | return _urlToFilter.createRelativeURL(); 50 | } 51 | 52 | @Override 53 | public String getFragment() 54 | { 55 | return _urlToFilter.getFragment(); 56 | } 57 | 58 | @Override 59 | public boolean getHasFragment() 60 | { 61 | return _urlToFilter.getHasFragment(); 62 | } 63 | 64 | @Override 65 | public boolean getHasHost() 66 | { 67 | return _urlToFilter.getHasHost(); 68 | } 69 | 70 | @Override 71 | public boolean getHasPath() 72 | { 73 | return _urlToFilter.getHasPath(); 74 | } 75 | 76 | @Override 77 | public boolean getHasPort() 78 | { 79 | return _urlToFilter.getHasPort(); 80 | } 81 | 82 | @Override 83 | public boolean getHasQueryParameters() 84 | { 85 | return _urlToFilter.getHasQueryParameters(); 86 | } 87 | 88 | @Override 89 | public boolean getHasScheme() 90 | { 91 | return _urlToFilter.getHasScheme(); 92 | } 93 | 94 | @Override 95 | public boolean getHasUserInfo() 96 | { 97 | return _urlToFilter.getHasUserInfo(); 98 | } 99 | 100 | @Override 101 | public String getHost() 102 | { 103 | return _urlToFilter.getHost(); 104 | } 105 | 106 | @Override 107 | public String getPath() 108 | { 109 | return _urlToFilter.getPath(); 110 | } 111 | 112 | @Override 113 | public List getPathComponents() 114 | { 115 | return _urlToFilter.getPathComponents(); 116 | } 117 | 118 | @Override 119 | public int getPort() 120 | { 121 | return _urlToFilter.getPort(); 122 | } 123 | 124 | @Override 125 | public Query getQuery() 126 | { 127 | return _urlToFilter.getQuery(); 128 | } 129 | 130 | @Override 131 | public String getQueryString() 132 | { 133 | return _urlToFilter.getQueryString(); 134 | } 135 | 136 | @Override 137 | public String getScheme() 138 | { 139 | return _urlToFilter.getScheme(); 140 | } 141 | 142 | @Override 143 | public String getURL() 144 | { 145 | return _urlToFilter.getURL(); 146 | } 147 | 148 | @Override 149 | public String getUserInfo() 150 | { 151 | return _urlToFilter.getUserInfo(); 152 | } 153 | 154 | /** 155 | * @return this object as a {@link URL} 156 | */ 157 | @Override 158 | public java.net.URL toJavaURL() 159 | { 160 | return _urlToFilter.toJavaURL(); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/url/Query.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.url; 18 | 19 | import java.util.Iterator; 20 | import java.util.Map; 21 | 22 | /** 23 | * The interface which defines the query in a url. Only accessors. 24 | * 25 | * @author ypujante@linkedin.com 26 | */ 27 | public interface Query 28 | { 29 | /** 30 | * @return true if query parameters have been added */ 31 | boolean getHasQueryParameters(); 32 | 33 | /** 34 | * @return the iterator of parameter names */ 35 | Iterator getParameterNames(); 36 | 37 | /** 38 | * @return the query as a string */ 39 | String getQuery(); 40 | 41 | /** 42 | * Gets the parameters given its name 43 | * 44 | * @param name the name of the parameter 45 | * @return the parameters or null if none found*/ 46 | String[] getParameterValues(String name); 47 | 48 | /** 49 | * @return the parameter map */ 50 | Map getParameterMap(); 51 | 52 | /** 53 | * Get the first parameter given its name 54 | * 55 | * @param name the name of the parameter 56 | * @return the first parameter */ 57 | String getParameter(String name); 58 | 59 | /** 60 | * @return the encoding used by the query */ 61 | String getEncoding(); 62 | 63 | /** 64 | * Gets the first parameter given its name and converts it to the given boolean type. 65 | * 66 | * @param name the name of the parameter 67 | * @return true if parmaeterValue equals the name that is given, or if it is one of the following strings 68 | * 'yes', 'true', 'on' 69 | */ 70 | boolean getBooleanParameter(String name); 71 | 72 | /** 73 | * Gets the first parameter given its name and converts it to int 74 | * @param name 75 | * @param defaultValue 76 | * @return return an int, if parameter not found or parse exception, return default value 77 | */ 78 | int getIntParameter(String name, int defaultValue); 79 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/url/URL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.url; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * Interface which defines a url. Only accessors. 23 | * 24 | * @author ypujante@linkedin.com 25 | */ 26 | public interface URL 27 | { 28 | /** 29 | * @return the path */ 30 | String getPath(); 31 | 32 | /** 33 | * If the path is /a/b/c then returns a list containing 3 elements "a", "b" and "c" 34 | * @return the path splitted at each '/' and decoded 35 | */ 36 | List getPathComponents(); 37 | 38 | /** 39 | * @return the fragment */ 40 | String getFragment(); 41 | 42 | /** 43 | * @return the query string */ 44 | String getQueryString(); 45 | 46 | /** 47 | * @return the query */ 48 | Query getQuery(); 49 | 50 | /** 51 | * @return true if a path has been set */ 52 | boolean getHasPath(); 53 | 54 | /** 55 | * @return true if the fragment has been set */ 56 | boolean getHasFragment(); 57 | 58 | /** 59 | * @return true if query parameters have been added */ 60 | boolean getHasQueryParameters(); 61 | 62 | /** 63 | * @return the url */ 64 | String getURL(); 65 | 66 | String getScheme(); 67 | 68 | boolean getHasScheme(); 69 | 70 | String getUserInfo(); 71 | 72 | boolean getHasUserInfo(); 73 | 74 | String getHost(); 75 | 76 | boolean getHasHost(); 77 | 78 | int getPort(); 79 | 80 | boolean getHasPort(); 81 | 82 | /** 83 | * @return a url which is relative (does not contain anything before path) 84 | */ 85 | public URL createRelativeURL(); 86 | 87 | /** 88 | * @return this object as a {@link java.net.URL} 89 | */ 90 | public java.net.URL toJavaURL(); 91 | } -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/url/URLCodec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.url; 18 | 19 | import org.linkedin.util.text.TextUtils; 20 | 21 | import java.io.UnsupportedEncodingException; 22 | import java.io.Serializable; 23 | import java.net.URLEncoder; 24 | import java.net.URLDecoder; 25 | 26 | /** 27 | * @author ypujante@linkedin.com 28 | * 29 | */ 30 | public class URLCodec implements Serializable 31 | { 32 | private static final long serialVersionUID = 1L; 33 | 34 | public static final URLCodec INSTANCE = new URLCodec(false); 35 | 36 | public static URLCodec instance() 37 | { 38 | return INSTANCE; 39 | } 40 | 41 | public static final String CHARACTER_ENCODING = "UTF-8"; 42 | 43 | private final boolean _encodeDot; 44 | private final String _characterEncoding; 45 | 46 | /** 47 | * Constructor 48 | */ 49 | public URLCodec(boolean encodeDot, String characterEncoding) 50 | throws UnsupportedEncodingException 51 | { 52 | _encodeDot = encodeDot; 53 | "".getBytes(characterEncoding); // checks for availabitity of encoding 54 | _characterEncoding = characterEncoding; 55 | } 56 | 57 | /** 58 | * Constructor 59 | */ 60 | public URLCodec(boolean encodeDot) 61 | { 62 | _encodeDot = encodeDot; 63 | _characterEncoding = CHARACTER_ENCODING; // we know that it is supported! 64 | } 65 | 66 | /** 67 | * Constructor 68 | */ 69 | public URLCodec() 70 | { 71 | this(false); 72 | } 73 | 74 | public String getCharacterEncoding() 75 | { 76 | return _characterEncoding; 77 | } 78 | 79 | public boolean isEncodeDot() 80 | { 81 | return _encodeDot; 82 | } 83 | 84 | /** 85 | * Encapsulates the call to encoding a URL 86 | * 87 | * @param original the string to encode 88 | * @return the encoded url */ 89 | public String urlEncode(String original) 90 | { 91 | // see http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars 92 | // for an explanation of the character encoding 93 | String s = null; 94 | try 95 | { 96 | s = URLEncoder.encode(original, _characterEncoding); 97 | } 98 | catch(UnsupportedEncodingException e) 99 | { 100 | throw new RuntimeException(e); 101 | } 102 | 103 | if(_encodeDot) 104 | { 105 | // we encode . as well because it can cause problems in url in emails. 106 | s = TextUtils.searchAndReplace(s, ".", "%2E"); 107 | } 108 | 109 | return s; 110 | } 111 | 112 | /** 113 | * Encapsulates the call to decoding a URL so that we don't have to deal 114 | * with the encoding. 115 | * 116 | * @param original the string to decode 117 | * @return the encoded url */ 118 | public String urlDecode(String original) 119 | { 120 | try 121 | { 122 | return URLDecoder.decode(original, _characterEncoding); 123 | } 124 | catch(UnsupportedEncodingException e) 125 | { 126 | throw new RuntimeException(e); 127 | } 128 | } 129 | 130 | @Override 131 | public boolean equals(Object o) 132 | { 133 | if(this == o) return true; 134 | if(o == null || getClass() != o.getClass()) return false; 135 | 136 | URLCodec urlCodec = (URLCodec) o; 137 | 138 | if(_encodeDot != urlCodec._encodeDot) return false; 139 | if(_characterEncoding != null ? 140 | !_characterEncoding.equals(urlCodec._characterEncoding) : 141 | urlCodec._characterEncoding != null) return false; 142 | 143 | return true; 144 | } 145 | 146 | @Override 147 | public int hashCode() 148 | { 149 | int result = (_encodeDot ? 1 : 0); 150 | result = 31 * result + (_characterEncoding != null ? _characterEncoding.hashCode() : 0); 151 | return result; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/main/java/org/linkedin/util/xml/AbstractXMLBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.util.xml; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * Define some methods in terms of others so that there is less code to 23 | * implement in further implementation. 24 | * 25 | * @author ypujante@linkedin.com */ 26 | public abstract class AbstractXMLBuilder implements XMLBuilder 27 | { 28 | /** 29 | * Constructor */ 30 | public AbstractXMLBuilder() 31 | { 32 | } 33 | 34 | /** 35 | * Adds a tag 36 | * 37 | * @param tagName the name of the tag to add 38 | * @param value the value of the tag to add */ 39 | @Override 40 | public void addTag(String tagName, int value) 41 | { 42 | addTag(tagName, String.valueOf(value)); 43 | } 44 | 45 | /** 46 | * Adds a tag 47 | * 48 | * @param tagName the name of the tag to add 49 | * @param value the value of the tag to add */ 50 | @Override 51 | public void addTag(String tagName, double value) 52 | { 53 | addTag(tagName, String.valueOf(value)); 54 | } 55 | 56 | /** 57 | * Adds a tag which contains an attribute 58 | * 59 | * @param tagName the name of the tag to add 60 | * @param value the value of the tag to add 61 | * @param attrName the name of the attribute 62 | * @param attrValue the value of the attribute */ 63 | @Override 64 | public void addTag(String tagName, 65 | int value, 66 | String attrName, 67 | String attrValue) 68 | { 69 | addTag(tagName, String.valueOf(value), attrName, attrValue); 70 | } 71 | 72 | /** 73 | * Adds a tag which contains an attribute 74 | * 75 | * @param tagName the name of the tag to add 76 | * @param value the value of the tag to add 77 | * @param attrName the name of the attribute 78 | * @param attrValue the value of the attribute */ 79 | @Override 80 | public void addTag(String tagName, 81 | double value, 82 | String attrName, 83 | String attrValue) 84 | { 85 | addTag(tagName, String.valueOf(value), attrName, attrValue); 86 | } 87 | 88 | /** 89 | * Adds a tag which contains the attributes specified. All the 90 | * properties will be turned into attributes. 91 | * 92 | * @param tagName the name of the tag to add 93 | * @param value the value of the tag to add 94 | * @param attributes the attributes */ 95 | @Override 96 | public void addTag(String tagName, int value, Map attributes) 97 | { 98 | addTag(tagName, String.valueOf(value), attributes); 99 | } 100 | 101 | /** 102 | * Adds a tag which contains the attributes specified. All the 103 | * properties will be turned into attributes. 104 | * 105 | * @param tagName the name of the tag to add 106 | * @param value the value of the tag to add 107 | * @param attributes the attributes */ 108 | @Override 109 | public void addTag(String tagName, double value, Map attributes) 110 | { 111 | addTag(tagName, String.valueOf(value), attributes); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /org.linkedin.util-core/src/test/java/org/linkedin/util/io/resource/TestNullResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.util.io.resource; 19 | 20 | import junit.framework.TestCase; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * @author ypujante@linkedin.com 26 | * 27 | */ 28 | public class TestNullResource extends TestCase 29 | { 30 | /** 31 | * Constructor 32 | */ 33 | public TestNullResource(String name) 34 | { 35 | super(name); 36 | } 37 | 38 | public void testNullResource() throws IOException 39 | { 40 | NullResource r = NullResource.createFromRoot("/a/b"); 41 | 42 | checkNullResource(r); 43 | assertEquals("/", r.getPath()); 44 | assertEquals("", r.getFilename()); 45 | assertEquals("nullResource:/a/b", r.toURI().toString()); 46 | 47 | r = (NullResource) r.createRelative("/c"); 48 | checkNullResource(r); 49 | assertEquals("/c", r.getPath()); 50 | assertEquals("c", r.getFilename()); 51 | assertEquals("nullResource:/a/b/c", r.toURI().toString()); 52 | 53 | r = (NullResource) r.createRelative("/d"); 54 | checkNullResource(r); 55 | assertEquals("/c/d", r.getPath()); 56 | assertEquals("d", r.getFilename()); 57 | assertEquals("nullResource:/a/b/c/d", r.toURI().toString()); 58 | 59 | r = (NullResource) r.getParentResource(); 60 | checkNullResource(r); 61 | assertEquals("/c", r.getPath()); 62 | assertEquals("c", r.getFilename()); 63 | assertEquals("nullResource:/a/b/c", r.toURI().toString()); 64 | } 65 | 66 | private void checkNullResource(Resource r) throws IOException 67 | { 68 | assertFalse(r.exists()); 69 | assertFalse(r.isDirectory()); 70 | assertEquals(0L, r.lastModified()); 71 | assertEquals(0L, r.length()); 72 | assertNull(r.list()); 73 | 74 | try 75 | { 76 | r.getInfo(); 77 | fail("should fail with excpetion"); 78 | } 79 | catch(IOException e) 80 | { 81 | // ok 82 | } 83 | try 84 | { 85 | r.getInputStream(); 86 | fail("should fail with excpetion"); 87 | } 88 | catch(IOException e) 89 | { 90 | // ok 91 | } 92 | try 93 | { 94 | r.getFile(); 95 | fail("should fail with excpetion"); 96 | } 97 | catch(IOException e) 98 | { 99 | // ok 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * Portions Copyright 2012-2013 Yan Pujante 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | 18 | apply plugin: 'groovy' 19 | apply plugin: 'org.linkedin.release' 20 | 21 | dependencies { 22 | compile project(':org.linkedin.util-core') 23 | compile spec.external.ant 24 | compile spec.external.slf4j 25 | compile spec.external.slf4jJul 26 | compile spec.external.log4j 27 | compile spec.external.json 28 | compile spec.external.jacksoncore 29 | compile spec.external.jacksondatabind 30 | compile spec.external.groovy 31 | 32 | testCompile spec.external.junit 33 | testRuntime spec.external.slf4jLog4j 34 | } 35 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/ant/AntUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * Portions Copyright (c) 2011-2013 Yan Pujante 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | 18 | 19 | package org.linkedin.groovy.util.ant 20 | 21 | import org.apache.tools.ant.Project 22 | import org.apache.tools.ant.BuildException 23 | import org.apache.tools.ant.RuntimeConfigurable 24 | import org.apache.tools.ant.Target 25 | import org.apache.tools.ant.Task 26 | 27 | /** 28 | * Helper methods for ant 29 | * 30 | * @author ypujante@linkedin.com 31 | */ 32 | class AntUtils 33 | { 34 | /** 35 | * Executes the closure with a builder and make sure to catch BuildException 36 | * to propertly unwrap them 37 | */ 38 | static def withBuilder(Closure closure) 39 | { 40 | AntBuilder6068 builder = new AntBuilder6068() 41 | // removes info messages... 42 | builder.project.buildListeners[0].messageOutputLevel = Project.MSG_WARN 43 | try 44 | { 45 | return closure(builder) 46 | } 47 | catch(BuildException e) 48 | { 49 | if(e.cause) 50 | throw e.cause 51 | else 52 | throw e 53 | } 54 | } 55 | 56 | /** 57 | * Creates the directory and parents of the provided directory. Returns dir. 58 | */ 59 | static File mkdirs(File dir) 60 | { 61 | AntUtils.withBuilder { ant -> ant.mkdir(dir: dir) } 62 | return dir 63 | } 64 | 65 | /** 66 | * Returns a temp file located in System.getProperty('java.io.tmpdir') 67 | */ 68 | static File tempFile() 69 | { 70 | return tempFile([:]) 71 | } 72 | 73 | /** 74 | * Creates a temp file: 75 | * 76 | * @param args.destdir where the file should be created (optional (will go in 77 | * System.getProperty('java.io.tmpdir')) 78 | * @param args.prefix a prefix for the file (optional) 79 | * @param args.suffix a suffix for the file (optional) 80 | * @param args.deleteonexit if the temp file should be deleted on exit (default to 81 | * false) 82 | * @param args.createParents if the parent directories should be created (default to 83 | * true) 84 | * @return a file (note that it is just a file object and that the actual file has *not* been 85 | * created and the parents may have been depending on the args.createParents value) 86 | */ 87 | static File tempFile(args) 88 | { 89 | args = args ?: [:] 90 | args = new HashMap(args) 91 | args.destdir = args.destdir ?: System.getProperty('java.io.tmpdir') 92 | args.prefix = args.prefix ?: '' 93 | args.deleteonexit = args.deleteonexit ?: false 94 | args.property = 'p' 95 | def tempFile = AntUtils.withBuilder { ant -> ant.tempfile(args).project.getProperty('p') } 96 | tempFile = new File(tempFile) 97 | if(args.createParents == null ? true : args.createParent) 98 | { 99 | mkdirs(tempFile.parentFile) 100 | } 101 | return tempFile 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/cli/CliUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.cli 18 | 19 | /** 20 | * Utilities methods for cli (cli builder) 21 | * 22 | * @author ypujante@linkedin.com 23 | */ 24 | class CliUtils 25 | { 26 | /** 27 | * Parses the cli options and returns them as well as a ConfigObject where each key 28 | * is the long option and value is the value of the option 29 | * 30 | * @param params.cli the CliBuilder instance (required) 31 | * @param params.args the command line arguments (required) 32 | * @param params.configFileOption the (short) name of an option that would contain a config file 33 | * to read (optional) 34 | * @return a map [config: c, options: o] 35 | */ 36 | 37 | static def parseCliOptions(params) 38 | { 39 | def options = params.cli.parse(params.args) 40 | 41 | if(!options) 42 | { 43 | params.cli.usage() 44 | return null 45 | } 46 | 47 | Properties properties = new Properties() 48 | 49 | if(params.configFileOption) 50 | { 51 | def configFile = options."${params.configFileOption}" 52 | if(configFile) 53 | { 54 | new File(configFile).withInputStream { 55 | properties.load(it) 56 | } 57 | } 58 | } 59 | 60 | params.cli.options.options.each { option -> 61 | def value = options."${option.opt}" 62 | if(value != false) 63 | properties[option.longOpt] = value 64 | } 65 | 66 | [ 67 | config: new ConfigSlurper().parse(properties), 68 | options: options 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/config/Config.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.config 18 | 19 | /** 20 | * @author ypujante@linkedin.com 21 | */ 22 | class Config 23 | { 24 | static String getRequiredString(config, String name) 25 | { 26 | String value = getOptionalString(config, name, null) 27 | if(value == null) 28 | throw new MissingConfigParameterException(name) 29 | return value 30 | } 31 | 32 | static String getOptionalString(config, String name, String defaultValue) 33 | { 34 | def value = config?."${name}" 35 | 36 | if(value == null) 37 | value = defaultValue 38 | 39 | return value?.toString() 40 | } 41 | 42 | static boolean getOptionalBoolean(config, String name, boolean defaultValue) 43 | { 44 | def value = config?."${name}" 45 | 46 | String param = value?.toString()?.toLowerCase() 47 | 48 | if(param == null) 49 | return defaultValue 50 | 51 | switch(param) 52 | { 53 | case 'true': 54 | case 'yes': 55 | case 'on': 56 | return true 57 | 58 | case 'false': 59 | case 'no': 60 | case 'off': 61 | return false 62 | } 63 | 64 | throw new IllegalArgumentException("not a boolean : " + param); 65 | } 66 | 67 | static int getOptionalInt(config, String name, int defaultValue) 68 | { 69 | def value = config?."${name}" 70 | 71 | if(value == null) 72 | return defaultValue 73 | 74 | return value as int 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/config/MissingConfigParameterException.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.config 18 | 19 | /** 20 | * @author ypujante@linkedin.com 21 | */ 22 | class MissingConfigParameterException extends RuntimeException 23 | { 24 | private static final long serialVersionUID = 1L; 25 | 26 | public MissingConfigParameterException() { super(); } 27 | public MissingConfigParameterException(String msg) { super(msg); } 28 | } 29 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/ivy/IvyURLHandler.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * Portions Copyright (c) 2011 Yan Pujante 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | 18 | package org.linkedin.groovy.util.ivy 19 | 20 | import groovy.xml.NamespaceBuilder 21 | import org.linkedin.groovy.util.io.GroovyIOUtils 22 | import org.linkedin.util.io.PathUtils 23 | import org.linkedin.groovy.util.ant.AntUtils 24 | 25 | /** 26 | * Handle ivy:/organisation/name/version style urls 27 | * 28 | * @author ypujante@linkedin.com */ 29 | class IvyURLHandler extends URLStreamHandler 30 | { 31 | private final def _defaultIvySettings 32 | 33 | IvyURLHandler(defaultIvySettings) 34 | { 35 | _defaultIvySettings = defaultIvySettings 36 | } 37 | 38 | protected URLConnection openConnection(URL url) 39 | { 40 | def ivyCoordinates = PathUtils.removeLeadingSlash(url.path).split('/') 41 | return new IvyURLConnection(url, _defaultIvySettings, ivyCoordinates); 42 | } 43 | 44 | protected void parseURL(URL u, String spec, int start, int limit) 45 | { 46 | super.parseURL(u, spec, start, limit) 47 | 48 | if(u.getHost() || u.getPort() != -1) 49 | throw new UnsupportedOperationException("host/port not supported yet") 50 | 51 | if(u.getQuery()) 52 | throw new IllegalArgumentException("no query string is allowed") 53 | 54 | def ivyCoordinates = PathUtils.removeLeadingSlash(u.path).split('/') 55 | if(ivyCoordinates.size() < 3 || ivyCoordinates.size() > 4) 56 | throw new IllegalArgumentException("Bad ivy coordinates: ${u}") 57 | } 58 | } 59 | 60 | /** 61 | * Handle ivy:/organisation/name/version style urls 62 | * 63 | * @author ypujante@linkedin.com */ 64 | class IvyURLConnection extends URLConnection 65 | { 66 | private final def _ivySettings 67 | private final def _ivyCoordinates 68 | 69 | private def _files 70 | 71 | IvyURLConnection(URL url, ivySettings, ivyCoordinates) 72 | { 73 | super(url) 74 | _ivySettings = ivySettings 75 | _ivyCoordinates = ivyCoordinates 76 | } 77 | 78 | public void connect() 79 | { 80 | AntUtils.withBuilder { ant -> 81 | def ivy = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.ivy.ant') 82 | 83 | GroovyIOUtils.withFile(_ivySettings) { File ivySettingsFile -> 84 | ivy.settings(file: ivySettingsFile) 85 | 86 | ivy.cachefileset(setid: 'fetchFromIvy', 87 | conf: _ivyCoordinates.size() == 4 ? _ivyCoordinates[3] : 'default', 88 | inline: true, 89 | organisation: _ivyCoordinates[0], 90 | module: _ivyCoordinates[1], 91 | revision: _ivyCoordinates[2]) 92 | 93 | _files = ant.project.getReference('fetchFromIvy').collect { it.file } 94 | } 95 | } 96 | connected = true 97 | } 98 | 99 | void disconnect() 100 | { 101 | connected = false 102 | // nothing to do... 103 | } 104 | 105 | def getFiles() 106 | { 107 | return _files 108 | } 109 | 110 | public InputStream getInputStream() 111 | { 112 | if (!connected) 113 | connect() 114 | 115 | if(_files.size() != 1) 116 | { 117 | throw new IOException("not 1 artifact downloaded for ${_ivyCoordinates}: ${_files}") 118 | } 119 | 120 | return new FileInputStream(_files[0]) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/JulToSLF4jBridge.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * Portions Copyright (c) 2013 Yan Pujante 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | 18 | package org.linkedin.groovy.util.log 19 | 20 | import java.util.logging.LogManager 21 | import org.slf4j.bridge.SLF4JBridgeHandler 22 | 23 | /** 24 | * @author ypujante@linkedin.com 25 | */ 26 | class JulToSLF4jBridge 27 | { 28 | /** 29 | * The problem with SLF4JBridgeHandler.install() method is that it does not 30 | * remove the other handlers and as a result logs still make it the 'old' way. 31 | */ 32 | synchronized static void installBridge() 33 | { 34 | if(!SLF4JBridgeHandler.isInstalled()) 35 | { 36 | def rootLogger = LogManager.getLogManager().getLogger("") 37 | 38 | rootLogger.handlers.each { 39 | rootLogger.removeHandler(it) 40 | } 41 | 42 | rootLogger.addHandler(new SLF4JBridgeHandler()) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/MaskDataPatternConverter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.log 18 | 19 | import org.apache.log4j.helpers.PatternConverter; 20 | import org.apache.log4j.spi.LoggingEvent 21 | import org.apache.log4j.spi.ThrowableInformation 22 | import java.util.regex.Pattern 23 | import java.util.regex.Matcher 24 | 25 | /** 26 | * @author mdubey@linkedin.com 27 | * 28 | * Created: Aug 2, 2010 1:32:04 PM 29 | */ 30 | class MaskDataPatternConverter extends PatternConverter 31 | { 32 | boolean processThrowable 33 | def maskingMap 34 | 35 | public MaskDataPatternConverter(String maskingRegex, boolean processThrowable) 36 | { 37 | super(); 38 | this.processThrowable = processThrowable 39 | 40 | // load the maskingRegex as a map 41 | if (maskingRegex) { 42 | GroovyShell groovysh = new GroovyShell() 43 | this.maskingMap = groovysh.evaluate(maskingRegex) 44 | // optimzation to store precompiled pattern in the map 45 | // def newMap = [:] 46 | // maskingMap.each { k, v -> 47 | // if(k instanceof String) 48 | // k = Pattern.compile(k) 49 | // newMap[k] = v 50 | // } 51 | // maskingMap = newMap 52 | } 53 | } 54 | 55 | @Override 56 | protected String convert(LoggingEvent event) 57 | { 58 | if (processThrowable) { 59 | ThrowableInformation information = event.getThrowableInformation() 60 | StringBuilder builder = new StringBuilder() 61 | 62 | if (information != null) { 63 | String[] stringRep = information.getThrowableStrRep() 64 | 65 | int length = stringRep.length; 66 | for (int i = 0; i < length; i++) { 67 | String string = stringRep[i] 68 | builder.append(maskSensitiveData(string)).append("\n") 69 | } 70 | } 71 | return builder.toString() 72 | 73 | } else { 74 | // convert message to filter out any encrypted data 75 | return maskSensitiveData(event.getRenderedMessage()) 76 | 77 | } 78 | 79 | } 80 | 81 | private String maskSensitiveData(String message) 82 | { 83 | if (maskingMap) { 84 | maskingMap.each { entry -> 85 | def pat = entry.key 86 | Closure c = entry.value 87 | message = message.replaceAll(pat) { Object[] it -> 88 | def updated = c(it) 89 | return updated 90 | } 91 | } 92 | } 93 | return message 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/MaskDataPatternLayout.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.log 18 | 19 | import org.apache.log4j.PatternLayout 20 | import org.apache.log4j.helpers.PatternParser 21 | 22 | /** 23 | * Add support for filtering log message based on regex. This is mainly used to make sure we do not log sensitive information 24 | * in log files. 25 | * 26 | * This is achieved by adding a new option '%w' (inverted m) that processed the message for filtering. In log4j config MaskingRegex 27 | * should also be defined that contains these filters and actions as a groovy closure. 28 | * 29 | * Ex: 30 | * 31 | * 32 | * 33 | * 36 | * 42 | * 43 | * 44 | * @author mdubey@linkedin.com 45 | * 46 | * Created: Aug 2, 2010 12:57:15 PM 47 | */ 48 | public class MaskDataPatternLayout extends PatternLayout { 49 | 50 | String maskingRegex; 51 | 52 | @Override 53 | public void activateOptions() 54 | { 55 | // This call on super forces a call to createPatternParser, which we need to get Parser setup correctly 56 | setConversionPattern(getConversionPattern()) 57 | } 58 | 59 | @Override 60 | protected PatternParser createPatternParser(String pattern) { 61 | return new MaskDataPatternParser(pattern, getMaskingRegex()); 62 | } 63 | 64 | public void setMaskingRegex(String maskingRegex) 65 | { 66 | this.maskingRegex = maskingRegex 67 | } 68 | 69 | public String getMaskingRegex() 70 | { 71 | return maskingRegex; 72 | } 73 | 74 | @Override 75 | public boolean ignoresThrowable() 76 | { 77 | return false; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/MaskDataPatternParser.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.log 18 | 19 | import org.apache.log4j.helpers.PatternParser 20 | 21 | /** 22 | * @author mdubey@linkedin.com 23 | * 24 | * Created: Aug 2, 2010 1:29:10 PM 25 | */ 26 | class MaskDataPatternParser extends PatternParser 27 | { 28 | private static final char MASKED_MESSAGE_CHAR = 'w' // looks like inverted m and is unused by PatternLayout 29 | private static final char MASKED_THROWABLE_CHAR = 's' // for use by printStacktrace 30 | 31 | private String maskingRegex 32 | 33 | public MaskDataPatternParser(String pattern, String maskingRegex) { 34 | super(pattern); 35 | this.maskingRegex = maskingRegex; 36 | } 37 | 38 | @Override 39 | protected void finalizeConverter(char c) { 40 | switch (c) { 41 | case MASKED_MESSAGE_CHAR: 42 | currentLiteral.setLength(0); 43 | addConverter(new MaskDataPatternConverter(maskingRegex, false)); 44 | break; 45 | case MASKED_THROWABLE_CHAR: 46 | currentLiteral.setLength(0); 47 | addConverter(new MaskDataPatternConverter(maskingRegex, true)); 48 | break; 49 | default: 50 | super.finalizeConverter(c); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/mop/GroovyMopUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.groovy.util.mop 19 | 20 | /** 21 | * This class contains utility methods for meta programming 22 | * 23 | * @author ypujante@linkedin.com 24 | */ 25 | class GroovyMopUtils 26 | { 27 | /** 28 | * This method should be called from a missingMethod handler. It looks up a set of delegates 29 | * as an alternate for the method call (note that the order of the delegates matters). If a 30 | * delegate is found, it is automatically added as a new method to not have any penalty 31 | * with future calls 32 | */ 33 | static def missingMethodDelegate(o, name, args, delegates) 34 | { 35 | // try to locate a delegate which can answer the call 36 | def delegate = delegates.find {it?.metaClass?.respondsTo(it, name, args) } 37 | 38 | if(delegate) 39 | { 40 | def methods = delegate.metaClass.respondsTo(delegate, name, args) 41 | // add the closure to o 42 | o.metaClass."${name}" << delegate.&"${name}" 43 | return methods[0].invoke(delegate, args) 44 | } 45 | else 46 | { 47 | throw new MissingMethodException("Unsupported call ${name}", o.class, args) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/net/SingletonURLStreamHandlerFactory.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.net 18 | 19 | /** 20 | * The singleton of url stream handler (can register only 1 per VM). 21 | * 22 | * @author ypujante@linkedin.com */ 23 | class SingletonURLStreamHandlerFactory implements URLStreamHandlerFactory 24 | { 25 | static SingletonURLStreamHandlerFactory INSTANCE = new SingletonURLStreamHandlerFactory() 26 | 27 | private final def _handlers = [:] 28 | 29 | public URLStreamHandler createURLStreamHandler(String protocol) 30 | { 31 | def handler 32 | 33 | synchronized(_handlers) 34 | { 35 | handler = _handlers[protocol] 36 | } 37 | 38 | if(!handler) 39 | return null 40 | 41 | if(handler instanceof Closure) 42 | return handler(protocol) 43 | else 44 | handler.createURLStreamHandler(protocol) 45 | } 46 | 47 | /** 48 | * Register a handler for the protocol 49 | */ 50 | void registerHandler(String protocol, handler) 51 | { 52 | synchronized(_handlers) 53 | { 54 | if(_handlers[protocol]) 55 | throw new IllegalStateException("already registered protocol ${protocol}".toString()) 56 | 57 | _handlers[protocol] = handler 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/rest/RestException.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.linkedin.groovy.util.rest 18 | 19 | import org.linkedin.groovy.util.json.JsonUtils 20 | 21 | /** 22 | * Exception which will contain the original exception (which may not be available in this VM)... 23 | * @author ypujante@linkedin.com */ 24 | class RestException extends Exception 25 | { 26 | private static final long serialVersionUID = 1L; 27 | 28 | public final String originalClassName 29 | public final String originalMessage 30 | 31 | RestException(String className, String message, StackTraceElement[] stackTrace) 32 | { 33 | super("class: ${className}, message: ${message}".toString()) 34 | originalClassName = className 35 | originalMessage = message 36 | setStackTrace(stackTrace) 37 | } 38 | 39 | /** 40 | * From a json representation (as built by {@link #toJSON(Throwable)) builds a rest exception 41 | */ 42 | static RestException fromJSON(jsonRepresentation) 43 | { 44 | def res = null 45 | def parent = null 46 | jsonRepresentation?.exception?.each { cause -> 47 | def ex = new RestException(cause.name, cause.message, rebuildStackTrace(cause.stackTrace)) 48 | if(res == null) 49 | res = ex 50 | parent?.initCause(ex) 51 | parent = ex 52 | } 53 | return res 54 | } 55 | 56 | /** 57 | * 'Serializes' the throwable into a json representation in order to be able to rebuild it later. 58 | */ 59 | static def toJSON(Throwable th) 60 | { 61 | if(th) 62 | { 63 | return JsonUtils.toJSON([exception: extractFullStackTrace(th, [])]) 64 | } 65 | else 66 | return null 67 | } 68 | 69 | private static StackTraceElement[] rebuildStackTrace(stackTrace) 70 | { 71 | def elements = [] 72 | 73 | stackTrace.each { ste -> 74 | elements << new StackTraceElement(ste.dc, ste.mn, ste.fn, ste.ln as int) 75 | } 76 | 77 | return elements as StackTraceElement[] 78 | } 79 | 80 | private static def extractFullStackTrace(exception, out) 81 | { 82 | if(exception) 83 | { 84 | out << [name: exception.getClass().name, message: exception.message, stackTrace: extractStackTrace(exception)] 85 | extractFullStackTrace(exception.cause, out) 86 | } 87 | 88 | return out 89 | } 90 | 91 | private static def extractStackTrace(exception) 92 | { 93 | def stackTrace = [] 94 | 95 | exception?.stackTrace?.each { ste -> 96 | stackTrace << [dc: ste.className, mn: ste.methodName, fn: ste.fileName, ln: ste.lineNumber] 97 | } 98 | 99 | return stackTrace 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/state/StateChangeListener.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | 18 | package org.linkedin.groovy.util.state 19 | 20 | /** 21 | * The callback for state changes. The callback implementation should be lightweight. 22 | * 23 | * @author ypujante@linkedin.com 24 | */ 25 | interface StateChangeListener 26 | { 27 | /** 28 | * On state change. Called only when the state (of the state machine) changes. It is called 29 | * with the new state (currentState/transitionState/error) 30 | */ 31 | void onStateChange(oldState, newState) 32 | } 33 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/java/org/linkedin/util/json/jackson/JacksonPrettyPrinter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yan Pujante 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.linkedin.util.json.jackson; 17 | 18 | import com.fasterxml.jackson.core.JsonGenerator; 19 | import com.fasterxml.jackson.core.PrettyPrinter; 20 | import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * Handles indentation levels + tighten output slightly 26 | * 27 | * @author yan@pongasoft.com 28 | */ 29 | public class JacksonPrettyPrinter implements PrettyPrinter 30 | { 31 | public static final DefaultPrettyPrinter.Indenter LF_2_SPACES_INDENTER = 32 | new DefaultPrettyPrinter.Lf2SpacesIndenter(); 33 | 34 | private final DefaultPrettyPrinter.Indenter _indenter; 35 | private int _nesting = 0; 36 | 37 | public JacksonPrettyPrinter(int indent) 38 | { 39 | super(); 40 | if(indent == 2) 41 | _indenter = LF_2_SPACES_INDENTER; 42 | else 43 | _indenter = new LfNSpacesIndenter(indent); 44 | } 45 | 46 | @Override 47 | public void writeRootValueSeparator(JsonGenerator jg) throws IOException 48 | { 49 | } 50 | 51 | private void writeIndentation(JsonGenerator jg) throws IOException 52 | { 53 | _indenter.writeIndentation(jg, _nesting); 54 | } 55 | 56 | @Override 57 | public void writeStartObject(JsonGenerator jg) throws IOException 58 | { 59 | jg.writeRaw('{'); 60 | _nesting++; 61 | } 62 | 63 | @Override 64 | public void writeEndObject(JsonGenerator jg, int nrOfEntries) 65 | throws IOException 66 | { 67 | _nesting--; 68 | writeIndentation(jg); 69 | jg.writeRaw('}'); 70 | } 71 | 72 | @Override 73 | public void writeObjectEntrySeparator(JsonGenerator jg) 74 | throws IOException 75 | { 76 | jg.writeRaw(','); 77 | writeIndentation(jg); 78 | } 79 | 80 | @Override 81 | public void writeObjectFieldValueSeparator(JsonGenerator jg) 82 | throws IOException 83 | { 84 | jg.writeRaw(": "); 85 | } 86 | 87 | @Override 88 | public void writeStartArray(JsonGenerator jg) throws IOException 89 | { 90 | jg.writeRaw('['); 91 | _nesting++; 92 | } 93 | 94 | @Override 95 | public void writeEndArray(JsonGenerator jg, int nrOfValues) 96 | throws IOException 97 | { 98 | _nesting--; 99 | writeIndentation(jg); 100 | jg.writeRaw(']'); 101 | } 102 | 103 | @Override 104 | public void writeArrayValueSeparator(JsonGenerator jg) throws IOException 105 | { 106 | jg.writeRaw(','); 107 | writeIndentation(jg); 108 | } 109 | 110 | @Override 111 | public void beforeArrayValues(JsonGenerator jg) throws IOException 112 | { 113 | writeIndentation(jg); 114 | } 115 | 116 | @Override 117 | public void beforeObjectEntries(JsonGenerator jg) throws IOException 118 | { 119 | writeIndentation(jg); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/main/java/org/linkedin/util/json/jackson/LfNSpacesIndenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yan Pujante 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.linkedin.util.json.jackson; 17 | 18 | import com.fasterxml.jackson.core.JsonGenerator; 19 | import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; 20 | 21 | import java.io.IOException; 22 | import java.util.Arrays; 23 | 24 | /** 25 | * Copied/adapted from jackson to handle N spaces instead of 2 26 | * 27 | * @author yan@pongasoft.com 28 | */ 29 | public class LfNSpacesIndenter implements DefaultPrettyPrinter.Indenter 30 | { 31 | private final int _numSpaces; 32 | 33 | /** 34 | * Constructor 35 | */ 36 | public LfNSpacesIndenter(int numSpaces) 37 | { 38 | if(numSpaces <= 0) 39 | throw new IllegalArgumentException(numSpaces + " must be > 0"); 40 | 41 | _numSpaces = numSpaces; 42 | } 43 | 44 | final static String SYSTEM_LINE_SEPARATOR; 45 | 46 | static 47 | { 48 | String lf = null; 49 | try 50 | { 51 | lf = System.getProperty("line.separator"); 52 | } 53 | catch(Throwable t) 54 | { 55 | t.printStackTrace(System.err); 56 | } // access exception? 57 | SYSTEM_LINE_SEPARATOR = (lf == null) ? "\n" : lf; 58 | } 59 | 60 | final static int SPACE_COUNT = 64; 61 | final static char[] SPACES = new char[SPACE_COUNT]; 62 | 63 | static 64 | { 65 | Arrays.fill(SPACES, ' '); 66 | } 67 | 68 | @Override 69 | public boolean isInline() 70 | { 71 | return false; 72 | } 73 | 74 | @Override 75 | public void writeIndentation(JsonGenerator jg, int level) 76 | throws IOException 77 | { 78 | jg.writeRaw(SYSTEM_LINE_SEPARATOR); 79 | // N spaces per level 80 | int numSpaces; 81 | // faster to add than multiply... 82 | switch(_numSpaces) 83 | { 84 | case 1: 85 | numSpaces = level; 86 | break; 87 | 88 | case 2: 89 | numSpaces = level + level; 90 | break; 91 | 92 | case 3: 93 | numSpaces = level + level + level; 94 | break; 95 | 96 | case 4: 97 | numSpaces = level + level + level + level; 98 | break; 99 | 100 | default: 101 | numSpaces = level * _numSpaces; 102 | break; 103 | } 104 | 105 | while(numSpaces > SPACE_COUNT) 106 | { // should never happen but... 107 | jg.writeRaw(SPACES, 0, SPACE_COUNT); 108 | numSpaces -= SPACES.length; 109 | } 110 | jg.writeRaw(SPACES, 0, numSpaces); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /org.linkedin.util-groovy/src/test/groovy/test/util/collections/TestGroovyCollectionsUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package test.util.collections 18 | 19 | import org.linkedin.groovy.util.collections.GroovyCollectionsUtils 20 | 21 | /** 22 | * @author ypujante@linkedin.com */ 23 | class TestGroovyCollectionsUtils extends GroovyTestCase 24 | { 25 | public void testMap() 26 | { 27 | assertTrue(GroovyCollectionsUtils.compareIgnoreType((Map) null, (Map) null)) 28 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(null, [:])) 29 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([:], null)) 30 | assertTrue(GroovyCollectionsUtils.compareIgnoreType([:], [:])) 31 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([a: null], [b: null])) 32 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([a: 1], [b: null])) 33 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new LinkedHashMap([a: 200, b: 21]), new TreeMap([a: 200, b: 21]))) 34 | } 35 | 36 | public void testList() 37 | { 38 | assertTrue(GroovyCollectionsUtils.compareIgnoreType((List) null, (List) null)) 39 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(null, [])) 40 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([], null)) 41 | assertTrue(GroovyCollectionsUtils.compareIgnoreType([], [])) 42 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([1], [null])) 43 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([null], [1])) 44 | assertTrue(GroovyCollectionsUtils.compareIgnoreType([1,2,3], [1,2,3])) 45 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new ArrayList([1,2,3]), new Vector([1,2,3]))) 46 | } 47 | 48 | public void testSet() 49 | { 50 | assertTrue(GroovyCollectionsUtils.compareIgnoreType((Set) null, (Set) null)) 51 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(null, new HashSet())) 52 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(new HashSet(), null)) 53 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new HashSet(), new HashSet())) 54 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(new HashSet([1]), new HashSet())) 55 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new HashSet([1,2,3]), new HashSet([1,2,3]))) 56 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new HashSet([3,2,1]), new LinkedHashSet([2,3,1]))) 57 | } 58 | 59 | public void testCollection() 60 | { 61 | assertTrue(GroovyCollectionsUtils.compareContent((Collection) null, (Collection) null)) 62 | assertFalse(GroovyCollectionsUtils.compareContent((Collection) null, new HashSet())) 63 | assertFalse(GroovyCollectionsUtils.compareContent(new HashSet(), (Collection) null)) 64 | assertTrue(GroovyCollectionsUtils.compareContent(new HashSet(), new ArrayList())) 65 | assertFalse(GroovyCollectionsUtils.compareContent(new HashSet([1]), new ArrayList())) 66 | assertTrue(GroovyCollectionsUtils.compareContent(new HashSet([1,2,3]), [1,2,3])) 67 | assertTrue(GroovyCollectionsUtils.compareContent([3,2,1], new LinkedHashSet([2,3,1]))) 68 | assertTrue(GroovyCollectionsUtils.compareContent([3,2,1], [1,2,3])) 69 | } 70 | 71 | public void testFlatten() 72 | { 73 | def src = 74 | [ 75 | k1: 'v1', 76 | k2: 77 | [ 78 | k21: 'v21', 79 | k22: ['v221', 'v222'] 80 | ], 81 | k3: ['v31', ['v321', 'v322'], [k33: 'v33']], 82 | k4: [], 83 | k5: [:], 84 | k6: ['v61', [], [:], 'v64'] 85 | ] 86 | 87 | def expected = [ 88 | k1: 'v1', 89 | 'k2.k21': 'v21', 90 | 'k2.k22[0]': 'v221', 91 | 'k2.k22[1]': 'v222', 92 | 'k3[0]': 'v31', 93 | 'k3[1][0]': 'v321', 94 | 'k3[1][1]': 'v322', 95 | 'k3[2].k33': 'v33', 96 | 'k6[0]': 'v61', 97 | 'k6[3]': 'v64' 98 | ] 99 | 100 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(expected, GroovyCollectionsUtils.flatten(src))) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /project-spec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2010 LinkedIn, Inc 3 | * Portions Copyright (c) 2011-2013 Yan Pujante 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | 18 | spec = [ 19 | name: 'linkedin-utils', 20 | group: 'org.linkedin', 21 | version: '1.9.0', 22 | 23 | versions: [ 24 | groovy: '2.0.7', 25 | jackson: '2.1.4', 26 | slf4j: '1.6.2' // to be compatible with grails 2.2.1 27 | ], 28 | 29 | // information about the build framework itself 30 | build: [ 31 | type: "gradle", 32 | commands: [ 33 | "snapshot": "gradlew xxx", 34 | "release": "gradlew -Prelease=true xxx" 35 | ] 36 | ] 37 | ] 38 | 39 | spec.scmUrl = "git@github.com:linkedin/${spec.name}.git" 40 | 41 | /** 42 | * External dependencies 43 | */ 44 | spec.external = [ 45 | ant: 'org.apache.ant:ant:1.8.2', 46 | groovy: "org.codehaus.groovy:groovy-all:${spec.versions.groovy}", 47 | json: 'org.json:json:20090211', 48 | jacksoncore: "com.fasterxml.jackson.core:jackson-core:${spec.versions.jackson}", 49 | jacksondatabind: "com.fasterxml.jackson.core:jackson-databind:${spec.versions.jackson}", 50 | junit: 'junit:junit:4.10', 51 | log4j: 'log4j:log4j:1.2.16', 52 | slf4j: "org.slf4j:slf4j-api:${spec.versions.slf4j}", 53 | slf4jLog4j: "org.slf4j:slf4j-log4j12:${spec.versions.slf4j}", 54 | slf4jJul: "org.slf4j:jul-to-slf4j:${spec.versions.slf4j}" 55 | ] 56 | -------------------------------------------------------------------------------- /repositories.gradle: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (c) 2010-2010 LinkedIn, Inc 4 | * Portions Copyright (c) 2013 Yan Pujante 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | * use this file except in compliance with the License. You may obtain a copy of 8 | * the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | * License for the specific language governing permissions and limitations under 16 | * the License. 17 | */ 18 | 19 | def topReleaseDir = new File(userConfig.top.release.dir ?: "${topBuildDir}/release").canonicalFile 20 | def topPublishDir = new File(userConfig.top.publish.dir ?: "${topBuildDir}/publish").canonicalFile 21 | 22 | /** 23 | * Repositories for build 24 | */ 25 | allRepositories.build = { 26 | add(new org.apache.ivy.plugins.resolver.FileSystemResolver()) { 27 | name = "build-release" 28 | addIvyPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[module]-[revision].ivy" 29 | addArtifactPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" 30 | m2compatible = true 31 | checkmodified = true 32 | } 33 | 34 | mavenRepo name: 'build-publish', url: topPublishDir.toURI() 35 | 36 | mavenCentral() 37 | } 38 | 39 | /** 40 | * Repositories for buildScript 41 | */ 42 | allRepositories.buildscript = allRepositories.build 43 | 44 | /** 45 | * Repositories for release 46 | */ 47 | allRepositories.snapshotRelease = { 48 | add(new org.apache.ivy.plugins.resolver.FileSystemResolver()) { 49 | name = 'local-release' 50 | addIvyPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[module]-[revision].ivy" 51 | addArtifactPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" 52 | m2compatible = true 53 | } 54 | } 55 | 56 | allRepositories.release = allRepositories.snapshotRelease 57 | 58 | /** 59 | * Repositories for publish 60 | */ 61 | allRepositories.snapshotPublish = { 62 | mavenDeployer { 63 | repository(url: "file://localhost${topPublishDir}") 64 | pom.whenConfigured { pomToConfigure -> 65 | pomToConfigure.project { 66 | name project.name 67 | description 'Set of utility classes used by other LinkedIn open source projects' 68 | url 'http://github.com/linkedin/linkedin-utils' 69 | licenses { 70 | license { 71 | name 'The Apache Software License, Version 2.0' 72 | url 'http://www.apache.org/licenses/LICENSE-2.0' 73 | } 74 | } 75 | developers { 76 | developer { 77 | id 'ypujante' 78 | name 'Yan Pujante' 79 | email 'yan@pongasoft.com' 80 | } 81 | developer { 82 | id 'mdubey' 83 | name 'Manish Dubey' 84 | email 'mdubey@linkedin.com' 85 | } 86 | } 87 | scm { 88 | connection "scm:git:${spec.scmUrl}" 89 | developerConnection "scm:git:${spec.scmUrl}" 90 | url spec.scmUrl 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | allRepositories.publish = allRepositories.snapshotPublish 98 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2010 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | include ':org.linkedin.util-core', 18 | ':org.linkedin.util-groovy' --------------------------------------------------------------------------------