103
103
import org .xml .sax .SAXException ;
104
104
105
105
import com .google .common .base .Preconditions ;
106
+ import com .google .common .base .Strings ;
106
107
107
- /**
108
+ /**
108
109
* Provides access to configuration parameters.
109
110
*
110
111
* <h4 id="Resources">Resources</h4>
@@ -2834,14 +2835,37 @@ public void writeXml(OutputStream out) throws IOException {
2834
2835
writeXml (new OutputStreamWriter (out , "UTF-8" ));
2835
2836
}
2836
2837
2837
- /**
2838
- * Write out the non-default properties in this configuration to the given
2839
- * {@link Writer}.
2840
- *
2838
+ public void writeXml (Writer out ) throws IOException {
2839
+ writeXml (null , out );
2840
+ }
2841
+
2842
+ /**
2843
+ * Write out the non-default properties in this configuration to the
2844
+ * given {@link Writer}.
2845
+ *
2846
+ * <li>
2847
+ * When property name is not empty and the property exists in the
2848
+ * configuration, this method writes the property and its attributes
2849
+ * to the {@link Writer}.
2850
+ * </li>
2851
+ * <p>
2852
+ *
2853
+ * <li>
2854
+ * When property name is null or empty, this method writes all the
2855
+ * configuration properties and their attributes to the {@link Writer}.
2856
+ * </li>
2857
+ * <p>
2858
+ *
2859
+ * <li>
2860
+ * When property name is not empty but the property doesn't exist in
2861
+ * the configuration, this method throws an {@link IllegalArgumentException}.
2862
+ * </li>
2863
+ * <p>
2841
2864
* @param out the writer to write to.
2842
2865
*/
2843
- public void writeXml (Writer out ) throws IOException {
2844
- Document doc = asXmlDocument ();
2866
+ public void writeXml (String propertyName , Writer out )
2867
+ throws IOException , IllegalArgumentException {
2868
+ Document doc = asXmlDocument (propertyName );
2845
2869
2846
2870
try {
2847
2871
DOMSource source = new DOMSource (doc );
@@ -2861,62 +2885,180 @@ public void writeXml(Writer out) throws IOException {
2861
2885
/**
2862
2886
* Return the XML DOM corresponding to this Configuration.
2863
2887
*/
2864
- private synchronized Document asXmlDocument () throws IOException {
2888
+ private synchronized Document asXmlDocument (String propertyName )
2889
+ throws IOException , IllegalArgumentException {
2865
2890
Document doc ;
2866
2891
try {
2867
- doc =
2868
- DocumentBuilderFactory .newInstance ().newDocumentBuilder ().newDocument ();
2892
+ doc = DocumentBuilderFactory
2893
+ .newInstance ()
2894
+ .newDocumentBuilder ()
2895
+ .newDocument ();
2869
2896
} catch (ParserConfigurationException pe ) {
2870
2897
throw new IOException (pe );
2871
2898
}
2899
+
2872
2900
Element conf = doc .createElement ("configuration" );
2873
2901
doc .appendChild (conf );
2874
2902
conf .appendChild (doc .createTextNode ("\n " ));
2875
2903
handleDeprecation (); //ensure properties is set and deprecation is handled
2876
- for (Enumeration <Object > e = properties .keys (); e .hasMoreElements ();) {
2877
- String name = (String )e .nextElement ();
2878
- Object object = properties .get (name );
2879
- String value = null ;
2880
- if (object instanceof String ) {
2881
- value = (String ) object ;
2882
- }else {
2883
- continue ;
2884
- }
2885
- Element propNode = doc .createElement ("property" );
2886
- conf .appendChild (propNode );
2887
-
2888
- Element nameNode = doc .createElement ("name" );
2889
- nameNode .appendChild (doc .createTextNode (name ));
2890
- propNode .appendChild (nameNode );
2891
-
2892
- Element valueNode = doc .createElement ("value" );
2893
- valueNode .appendChild (doc .createTextNode (value ));
2894
- propNode .appendChild (valueNode );
2895
-
2896
- if (updatingResource != null ) {
2897
- String [] sources = updatingResource .get (name );
2898
- if (sources != null ) {
2899
- for (String s : sources ) {
2900
- Element sourceNode = doc .createElement ("source" );
2901
- sourceNode .appendChild (doc .createTextNode (s ));
2902
- propNode .appendChild (sourceNode );
2904
+
2905
+ if (!Strings .isNullOrEmpty (propertyName )) {
2906
+ if (!properties .containsKey (propertyName )) {
2907
+ // given property not found, illegal argument
2908
+ throw new IllegalArgumentException ("Property " +
2909
+ propertyName + " not found" );
2910
+ } else {
2911
+ // given property is found, write single property
2912
+ appendXMLProperty (doc , conf , propertyName );
2913
+ conf .appendChild (doc .createTextNode ("\n " ));
2914
+ }
2915
+ } else {
2916
+ // append all elements
2917
+ for (Enumeration <Object > e = properties .keys (); e .hasMoreElements ();) {
2918
+ appendXMLProperty (doc , conf , (String )e .nextElement ());
2919
+ conf .appendChild (doc .createTextNode ("\n " ));
2920
+ }
2921
+ }
2922
+ return doc ;
2923
+ }
2924
+
2925
+ /**
2926
+ * Append a property with its attributes to a given {#link Document}
2927
+ * if the property is found in configuration.
2928
+ *
2929
+ * @param doc
2930
+ * @param conf
2931
+ * @param propertyName
2932
+ */
2933
+ private synchronized void appendXMLProperty (Document doc , Element conf ,
2934
+ String propertyName ) {
2935
+ // skip writing if given property name is empty or null
2936
+ if (!Strings .isNullOrEmpty (propertyName )) {
2937
+ String value = properties .getProperty (propertyName );
2938
+ if (value != null ) {
2939
+ Element propNode = doc .createElement ("property" );
2940
+ conf .appendChild (propNode );
2941
+
2942
+ Element nameNode = doc .createElement ("name" );
2943
+ nameNode .appendChild (doc .createTextNode (propertyName ));
2944
+ propNode .appendChild (nameNode );
2945
+
2946
+ Element valueNode = doc .createElement ("value" );
2947
+ valueNode .appendChild (doc .createTextNode (
2948
+ properties .getProperty (propertyName )));
2949
+ propNode .appendChild (valueNode );
2950
+
2951
+ Element finalNode = doc .createElement ("final" );
2952
+ finalNode .appendChild (doc .createTextNode (
2953
+ String .valueOf (finalParameters .contains (propertyName ))));
2954
+ propNode .appendChild (finalNode );
2955
+
2956
+ if (updatingResource != null ) {
2957
+ String [] sources = updatingResource .get (propertyName );
2958
+ if (sources != null ) {
2959
+ for (String s : sources ) {
2960
+ Element sourceNode = doc .createElement ("source" );
2961
+ sourceNode .appendChild (doc .createTextNode (s ));
2962
+ propNode .appendChild (sourceNode );
2963
+ }
2903
2964
}
2904
2965
}
2905
2966
}
2906
-
2907
- conf .appendChild (doc .createTextNode ("\n " ));
2908
2967
}
2909
- return doc ;
2910
2968
}
2911
2969
2912
2970
/**
2913
- * Writes out all the parameters and their properties (final and resource) to
2914
- * the given {@link Writer}
2915
- * The format of the output would be
2916
- * { "properties" : [ {key1,value1,key1.isFinal,key1.resource}, {key2,value2,
2917
- * key2.isFinal,key2.resource}... ] }
2918
- * It does not output the parameters of the configuration object which is
2919
- * loaded from an input stream.
2971
+ * Writes properties and their attributes (final and resource)
2972
+ * to the given {@link Writer}.
2973
+ *
2974
+ * <li>
2975
+ * When propertyName is not empty, and the property exists
2976
+ * in the configuration, the format of the output would be,
2977
+ * <pre>
2978
+ * {
2979
+ * "property": {
2980
+ * "key" : "key1",
2981
+ * "value" : "value1",
2982
+ * "isFinal" : "key1.isFinal",
2983
+ * "resource" : "key1.resource"
2984
+ * }
2985
+ * }
2986
+ * </pre>
2987
+ * </li>
2988
+ *
2989
+ * <li>
2990
+ * When propertyName is null or empty, it behaves same as
2991
+ * {@link #dumpConfiguration(Configuration, Writer)}, the
2992
+ * output would be,
2993
+ * <pre>
2994
+ * { "properties" :
2995
+ * [ { key : "key1",
2996
+ * value : "value1",
2997
+ * isFinal : "key1.isFinal",
2998
+ * resource : "key1.resource" },
2999
+ * { key : "key2",
3000
+ * value : "value2",
3001
+ * isFinal : "ke2.isFinal",
3002
+ * resource : "key2.resource" }
3003
+ * ]
3004
+ * }
3005
+ * </pre>
3006
+ * </li>
3007
+ *
3008
+ * <li>
3009
+ * When propertyName is not empty, and the property is not
3010
+ * found in the configuration, this method will throw an
3011
+ * {@link IllegalArgumentException}.
3012
+ * </li>
3013
+ * <p>
3014
+ * @param config the configuration
3015
+ * @param propertyName property name
3016
+ * @param out the Writer to write to
3017
+ * @throws IOException
3018
+ * @throws IllegalArgumentException when property name is not
3019
+ * empty and the property is not found in configuration
3020
+ **/
3021
+ public static void dumpConfiguration (Configuration config ,
3022
+ String propertyName , Writer out ) throws IOException {
3023
+ if (Strings .isNullOrEmpty (propertyName )) {
3024
+ dumpConfiguration (config , out );
3025
+ } else if (Strings .isNullOrEmpty (config .get (propertyName ))) {
3026
+ throw new IllegalArgumentException ("Property " +
3027
+ propertyName + " not found" );
3028
+ } else {
3029
+ JsonFactory dumpFactory = new JsonFactory ();
3030
+ JsonGenerator dumpGenerator = dumpFactory .createJsonGenerator (out );
3031
+ dumpGenerator .writeStartObject ();
3032
+ dumpGenerator .writeFieldName ("property" );
3033
+ appendJSONProperty (dumpGenerator , config , propertyName );
3034
+ dumpGenerator .writeEndObject ();
3035
+ dumpGenerator .flush ();
3036
+ }
3037
+ }
3038
+
3039
+ /**
3040
+ * Writes out all properties and their attributes (final and resource) to
3041
+ * the given {@link Writer}, the format of the output would be,
3042
+ *
3043
+ * <pre>
3044
+ * { "properties" :
3045
+ * [ { key : "key1",
3046
+ * value : "value1",
3047
+ * isFinal : "key1.isFinal",
3048
+ * resource : "key1.resource" },
3049
+ * { key : "key2",
3050
+ * value : "value2",
3051
+ * isFinal : "ke2.isFinal",
3052
+ * resource : "key2.resource" }
3053
+ * ]
3054
+ * }
3055
+ * </pre>
3056
+ *
3057
+ * It does not output the properties of the configuration object which
3058
+ * is loaded from an input stream.
3059
+ * <p>
3060
+ *
3061
+ * @param config the configuration
2920
3062
* @param out the Writer to write to
2921
3063
* @throws IOException
2922
3064
*/
@@ -2930,29 +3072,47 @@ public static void dumpConfiguration(Configuration config,
2930
3072
dumpGenerator .flush ();
2931
3073
synchronized (config ) {
2932
3074
for (Map .Entry <Object ,Object > item : config .getProps ().entrySet ()) {
2933
- dumpGenerator .writeStartObject ();
2934
- dumpGenerator .writeStringField ("key" , (String ) item .getKey ());
2935
- dumpGenerator .writeStringField ("value" ,
2936
- config .get ((String ) item .getKey ()));
2937
- dumpGenerator .writeBooleanField ("isFinal" ,
2938
- config .finalParameters .contains (item .getKey ()));
2939
- String [] resources = config .updatingResource .get (item .getKey ());
2940
- String resource = UNKNOWN_RESOURCE ;
2941
- if (resources != null && resources .length > 0 ) {
2942
- resource = resources [0 ];
2943
- }
2944
- dumpGenerator .writeStringField ("resource" , resource );
2945
- dumpGenerator .writeEndObject ();
3075
+ appendJSONProperty (dumpGenerator ,
3076
+ config ,
3077
+ item .getKey ().toString ());
2946
3078
}
2947
3079
}
2948
3080
dumpGenerator .writeEndArray ();
2949
3081
dumpGenerator .writeEndObject ();
2950
3082
dumpGenerator .flush ();
2951
3083
}
2952
-
3084
+
3085
+ /**
3086
+ * Write property and its attributes as json format to given
3087
+ * {@link JsonGenerator}.
3088
+ *
3089
+ * @param jsonGen json writer
3090
+ * @param config configuration
3091
+ * @param name property name
3092
+ * @throws IOException
3093
+ */
3094
+ private static void appendJSONProperty (JsonGenerator jsonGen ,
3095
+ Configuration config , String name ) throws IOException {
3096
+ // skip writing if given property name is empty or null
3097
+ if (!Strings .isNullOrEmpty (name ) && jsonGen != null ) {
3098
+ jsonGen .writeStartObject ();
3099
+ jsonGen .writeStringField ("key" , name );
3100
+ jsonGen .writeStringField ("value" , config .get (name ));
3101
+ jsonGen .writeBooleanField ("isFinal" ,
3102
+ config .finalParameters .contains (name ));
3103
+ String [] resources = config .updatingResource .get (name );
3104
+ String resource = UNKNOWN_RESOURCE ;
3105
+ if (resources != null && resources .length > 0 ) {
3106
+ resource = resources [0 ];
3107
+ }
3108
+ jsonGen .writeStringField ("resource" , resource );
3109
+ jsonGen .writeEndObject ();
3110
+ }
3111
+ }
3112
+
2953
3113
/**
2954
3114
* Get the {@link ClassLoader} for this job.
2955
- *
3115
+ *
2956
3116
* @return the correct class loader.
2957
3117
*/
2958
3118
public ClassLoader getClassLoader () {
0 commit comments