提交 8f89ef58 编写于 作者: C coffeys

Merge

......@@ -90,33 +90,26 @@ public class VerifyAccess {
if (allowedModes == 0) return false;
assert((allowedModes & PUBLIC) != 0 &&
(allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
// Usually refc and defc are the same, but if they differ, verify them both.
if (refc != defc) {
if (!isClassAccessible(refc, lookupClass, allowedModes)) {
// Note that defc is verified in the switch below.
return false;
}
if ((mods & (ALL_ACCESS_MODES|STATIC)) == (PROTECTED|STATIC) &&
(allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0) {
// Apply the special rules for refc here.
if (!isRelatedClass(refc, lookupClass))
return isSamePackage(defc, lookupClass);
// If refc == defc, the call to isPublicSuperClass will do
// the whole job, since in that case refc (as defc) will be
// a superclass of the lookup class.
}
// The symbolic reference class (refc) must always be fully verified.
if (!isClassAccessible(refc, lookupClass, allowedModes)) {
return false;
}
// Usually refc and defc are the same, but verify defc also in case they differ.
if (defc == lookupClass &&
(allowedModes & PRIVATE) != 0)
return true; // easy check; all self-access is OK
switch (mods & ALL_ACCESS_MODES) {
case PUBLIC:
if (refc != defc) return true; // already checked above
return isClassAccessible(refc, lookupClass, allowedModes);
return true; // already checked above
case PROTECTED:
if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
isSamePackage(defc, lookupClass))
return true;
if ((allowedModes & PROTECTED) == 0)
return false;
if ((mods & STATIC) != 0 &&
!isRelatedClass(refc, lookupClass))
return false;
if ((allowedModes & PROTECTED) != 0 &&
isSuperClass(defc, lookupClass))
return true;
......
package checker;
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
/**
* Represents the device configuration. The values are loaded from an XML file by JAXB.
*/
@XmlRootElement
public class Device {
@XmlElement()
private Map<Module, Integer> supportedModules = new EnumMap<>(Module.class);
/**
* Returns map of supported modules. The map key is module. The map value is version.
*
* @return map of supported modules.
*/
public Map<Module, Integer> getSupportedModules() {
return Collections.unmodifiableMap(supportedModules);
}
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Oracle nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This source code is provided to illustrate the usage of a given feature
or technique and has been deliberately simplified. Additional steps
required for a production-quality application, such as security checks,
input validation and proper error handling, might not be present in
this sample code.
-->
<device>
<supportedModules>
<entry>
<key>DISPLAY</key>
<value>2</value>
</entry>
<entry>
<key>THERMOMETER</key>
<value>1</value>
</entry>
<entry>
<key>CLOCK</key>
<value>4</value>
</entry>
</supportedModules>
</device>
\ No newline at end of file
package checker;
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/**
* Represents available modules.
*/
public enum Module {
DISPLAY, CLOCK, THERMOMETER, HEATER, SPEAKER, GSM, LED;
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package checker;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.xml.bind.JAXBContext;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.xml.bind.JAXBException;
/**
* Reads the device configuration from the XML file specified by -Adevice=device.xml.
* For each class in a project, checks required modules. If the device doesn't have
* the required module, then a compilation error will be shown.
*/
@SupportedAnnotationTypes("checker.RequireContainer")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class PluginChecker extends javax.annotation.processing.AbstractProcessor {
/**
* Name of the option to get the path to the xml with device configuration.
*/
public static final String DEVICE_OPTION = "device";
private Device device;
/**
* Only the device option is supported.
*
* {@inheritDoc}
*/
@Override
public Set<String> getSupportedOptions() {
return new HashSet<>(Arrays.asList(DEVICE_OPTION));
}
/**
* Initializes the processor by loading the device configuration.
*
* {@inheritDoc}
*/
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
try {
String deviceOption = processingEnv.getOptions().get(DEVICE_OPTION);
device = (Device) JAXBContext.newInstance(Device.class)
.createUnmarshaller().unmarshal(new File(deviceOption));
} catch (JAXBException e) {
throw new RuntimeException(
"Please specify device by -Adevice=device.xml\n"
+ e.toString(), e);
}
}
/**
* Processes @Require annotations and checks that Device meets requirements.
*
* {@inheritDoc}
*/
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
for (Element el : roundEnv.getElementsAnnotatedWith(RequireContainer.class)) {
for (Require req : el.getAnnotationsByType(Require.class)) {
//for every Require annotation checks if device has module of required version.
Integer version = device.getSupportedModules().get(req.value());
if (version == null
|| version < req.minVersion()
|| version > req.maxVersion()) {
//if module is optional then show only warning not error
if (req.optional()) {
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.WARNING,
"Plugin [" + el + "] requires " + req
+ "\n but device " + (version == null
? "doesn't have such module."
+ " This module is optional."
+ " So plugin will work but miss"
+ " some functionality"
: "has " + version
+ " version of that module"));
} else {
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.ERROR,
"Plugin [" + el + "] requires " + req
+ "\n but device "
+ (version == null
? "doesn't have such module"
: "has " + version
+ " version of that module"));
}
}
}
return true;
}
return false;
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package checker;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Indicates that a plug-in depends on a module.
*/
@Retention(RetentionPolicy.CLASS)
@Repeatable(RequireContainer.class)
public @interface Require {
/**
* Returns the required module.
*
* @return required module.
*/
Module value();
/**
* Returns the minimum supported version of a module.
*
* @return minimum supported version of a module.
*/
int minVersion() default 1;
/**
* Returns the maximum supported version of a module.
*
* @return maximum supported version of a module.
*/
int maxVersion() default Integer.MAX_VALUE;
/**
* Returns true if a module is optional. A module is optional if a system
* works without that module but is missing some functionality. Returns false if a system
* won't work without the specified module.
*
* @return true if module is optional. False otherwise.
*/
boolean optional() default false;
}
package checker;
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* A container for the repeatable @Require annotation.
*/
@Retention(RetentionPolicy.CLASS)
public @interface RequireContainer {
Require[] value();
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package plugins;
import checker.Module;
import checker.Require;
/**
* BoilerPlugin provides support for boiling water and keeping water warm.
*/
@Require(value = Module.CLOCK, maxVersion = 3)
@Require(value = Module.THERMOMETER)
@Require(value = Module.HEATER)
@Require(value = Module.LED, optional = true) //will use if present
public class BoilerPlugin {
/**
* Heats water up to 100 degrees Celsius.
*/
public void boil() {
boil(100);
}
/**
* Heats water up to temperature.
*
* @param temperature - desired temperature of the water in the boiler
*/
public void boil(int temperature) {
/*
* Turn on heater and wait while temperature reaches desired temperature
* in Celsius. Finally, turn off heater.
* If present, the LED light changes color according to the temperature.
*/
}
/**
* Keeps desired temperature.
*
* @param temperature - desired temperature of the water in the boiler
* @param seconds - period of time for checking temperature in seconds
*/
public void keepWarm(int temperature, int seconds) {
//Every n seconds check temperature and warm up, if necessary.
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package plugins;
import checker.Module;
import checker.Require;
import java.util.Calendar;
/**
* Introduces new features for BoilerPlugin. Features are boiling water by an
* SMS and boiling water by date with notification by a phone call.
*/
@Require(value = Module.SPEAKER)
@Require(value = Module.GSM, minVersion = 3)
@Require(value = Module.DISPLAY)
public class ExtendedBoilerPlugin extends BoilerPlugin {
/**
* Boils water at the appointed time and wakes you up by a ring and phone
* call. Shows "Good morning" and a quote of the day from the Internet on the
* display.
*
* @param calendar - date and time when water should be boiled
* @param phoneNumber - phone number to call
*/
public void boilAndWakeUp(Calendar calendar, int phoneNumber) {
//implementation
}
/**
* Boils water at the appointed time by getting an SMS of fixed format.
* Sends an SMS on finish.
*
* @param sms - text of SMS
*/
public void boilBySMS(String sms) {
//implementation
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package plugins;
import checker.Module;
import checker.Require;
/**
* Timer plug-in is used to support an alarm and a timer. It depends on Display and
* Clock modules.
*/
@Require(Module.DISPLAY)
@Require(value = Module.CLOCK, maxVersion = 3)
public class TimerPlugin {
/**
* Sets timer.
*
* @param time - the remaining time.
*/
public void timer(long time) {
//start timer
//show the remaining time on display
}
/**
* Sets alarm.
*
* @param time - the alarm time.
*/
public void alarm(long time) {
//start alarm
//show current time and alarm time on display
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import java.util.function.Supplier;
/**
* Supplies a positive number.
*/
@Validate(value = Validator.INTEGER_NUMBER,
description = "It's not an Integer ")
@Validate(value = Validator.POSITIVE_NUMBER,
description = "It's not a positive Number")
public class PositiveIntegerSupplier implements Supplier<String> {
/**
* Returns a string representation of a positive integer.
*
* @return string representation of a positive integer.
*/
@Override
public String get() {
return "20005"; //random number
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import javax.xml.bind.ValidationException;
import java.util.function.Supplier;
/**
* Validates the supplier.
*/
public class SupplierValidator {
/**
* Validates the supplier.
*
* @param supplier - Supplier that needs to be validated.
* @return true if supplier has passed validation check. False otherwise.
*/
public static boolean validate(Supplier<?> supplier) {
for (Validate annotation
: supplier.getClass().getAnnotationsByType(Validate.class)) {
try {
annotation.value().validate(supplier);
} catch (ValidationException e) {
System.out.println(annotation.description());
e.printStackTrace();
return false;
}
}
return true;
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Indicates that the class should be validated by the specified validator.
*/
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(ValidateContainer.class)
public @interface Validate {
/**
* Returns the validator that should validate the annotated class.
*
* @return Validator that should validate annotated class.
*/
Validator value();
/**
* Returns text to describe the failure of the validation check.
*
* @return text to describe the failure of the validation check.
*/
String description() default "";
}
/**
* A container for the repeatable @Validate annotation.
*
* @author Andrey Nazarov
*/
@Retention(RetentionPolicy.RUNTIME)
@interface ValidateContainer {
Validate[] value();
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import javax.xml.bind.ValidationException;
import java.util.function.Supplier;
/**
* Enum of Validator implementations.
*/
public enum Validator {
/**
* This validator checks that the string represents an integer.
*/
INTEGER_NUMBER {
/**
* Checks that the string represents an integer.
*
* @param string - a string supplier
* @throws ValidationException if the validation check fails
*/
@Override
void validate(Supplier<?> string) throws ValidationException {
try {
Integer.parseInt((String) string.get());
} catch (NumberFormatException ex) {
throw new ValidationException("Error while validating "
+ string.get());
}
}
},
/**
* This validator checks that the string represents a positive number.
*/
POSITIVE_NUMBER {
/**
* Checks that the string represents a positive number.
*
* @param string - an string supplier
* @throws ValidationException if the validation check fails
*/
@Override
void validate(Supplier<?> string) throws ValidationException {
try {
if (Double.compare(0.0, Double.parseDouble(
(String) string.get())) > 0) {
throw new Exception();
}
} catch (Exception ex) {
throw new ValidationException("Error while validating "
+ string.get());
}
}
};
/**
* Checks that the supplier is valid.
*
* @param string - a string supplier
* @throws ValidationException if validation check fails
*/
abstract void validate(Supplier<?> string) throws ValidationException;
}
<!DOCTYPE html>
<html>
<head>
<title>Repeating Annotations Demo</title>
</head>
<body>
<h2>Repeating Annotations Demo</h2>
<p>
This demo shows how to use repeating annotations at runtime and at compile time.
</p>
<ul>
<li><h3>Dependency checker.</h3>
<p>
Shows how to define repeating annotations and process them at compile time.
The problem domain is some code that performs useful operations on hardware devices.
The code relies on "modules" to be present on the devices. Applicability of the code to a particular
device is checked while compiling the code for a particular device.
A set of modules provided by a device is listed in an xml file that turns red during the compilation
phase and is compared with the required module set specified by annotations.
For instance, there is kettle with hardware modules: thermometer, display, and clock.
There is also a boiler plug-in that requires clock, thermometer, heater, and optionally an LED light.
Build the PluginChecker annotation processor first.
Then, run javac with the annotation processor against plug-in sources using the following command: </p>
<code>javac -cp "PluginChecker.jar" -processor checker.PluginChecker -Adevice=Kettle.xml -proc:only &lt;source
files&gt;</code>
<p>
where <code>PluginChecker.jar</code> - path to jar file that contains PluginChecker annotation processor
class. </br>
<code>Kettle.xml</code> - path to device descriptor Kettle.xml </br>
<code>&lt;source files&gt;</code> - source files in Plugins/src
</p>
For more information, see the source files.
</p>
<ul>
<li>Annotation processor sources: <a href="DependencyChecker/PluginChecker/src/">DependencyChecker/PluginChecker/src</a>
<li>Processing of repeating annotations can be found in <a href="DependencyChecker/PluginChecker/src/checker/PluginChecker.java">PluginChecker.java</a>
<li>Usage of repeating annotation is shown in modules sources.<a href="DependencyChecker/Plugins/src">DependencyChecker/Plugins/src</a>
</ul>
<li><h3>Validator.</h3>
<p>
Shows how to define repeating annotations and process them at runtime.
A problem domain is code that needs to validate provided Suppliers for conformance to some criteria.
The criteria are implemented by the Validator class which is applied by using annotations that are placed in
the code whenever validation is needed. For more information, see the
source files.
</p>
<p>
<ul>
<li>Usage of repeating annotation is described in <a href="Validator/src/PositiveIntegerSupplier.java">PositiveIntegerSupplier.java</a>
<li> Example of how to define a repeating annotation type can be found in
<a href="Validator/src/Validate.java">Validate.java</a>
<li> Usages of the new reflective methods can be found in <a href="Validator/src/SupplierValidator.java">SupplierValidator.java</a>
</ul>
</p>
Sources: <a href="Validator/src/">Validator/src/</a>
</ul>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Bulk Data Operations Demo</title>
</head>
<body>
<h2>Bulk Data Operations Demo</h2>
<p>
This demo shows how to use bulk data operations with the new JDK8
Collections API.
The demo also demonstrates new features of JDK8 such as lambda expressions
and method/constructor references.
</p>
<ul>
<li><h3>CSV Processor</h3>
<p>
Analyzes a CSV file, finds and collects useful information, computes
different statistics. For more information, see the source file.
</p>
Source: <a href="src/CSVProcessor.java">src/CSVProcessor.java</a>
<li><h3>Grep</h3>
<p>
Behaves like the standard Linux tool Grep. For more information, see
the source file.
</p>
Source: <a href="src/Grep.java">src/Grep.java</a>
<li><h3>PasswordGenerator</h3>
<p>
Produces a password of desired length. For more information see
source file.
</p>
Source: <a
href="src/PasswordGenerator.java">src/PasswordGenerator.java</a>
<li><h3>WC</h3>
<p>
Counts newlines, words, characters, and the maximum line length of a
text file. For more information, see the source
file.
</p>
Source: <a href="src/WC.java">src/WC.java</a>
</ul>
</body>
</html>
\ No newline at end of file
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation, and proper error handling, might not be present in
* this sample code.
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.*;
import java.util.regex.Pattern;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import static java.lang.Double.parseDouble;
import static java.util.stream.Collectors.*;
/**
* CSVProcessor is a tool for processing CSV files. There are several
* command-line options. Consult the {@link #printUsageAndExit} method for
* instructions and command line parameters. This sample shows examples of the
* following features:
* <ul>
* <li>Lambda and bulk operations. Working with streams: map(...), filter(...),
* sorted(...) methods. The collect(...) method with different collectors:
* Collectors.maxBy(...), Collectors.minBy(...), Collectors.toList(),
* Collectors.toCollection(...), Collectors.groupingBy(...),
* Collectors.toDoubleSummaryStatistics(...), and a custom Collector.</li>
* <li>Static method reference for printing values.</li>
* <li>Try-with-resources feature for closing files.</li>
* <li>Switch by String feature.</li>
* <li>Other new APIs: Pattern.asPredicate(), BinaryOperator
* BufferedReader.lines(), Collection.forEach(...), Comparator.comparing(...),
* Comparator.reversed(), Arrays.stream(...).</li>
* </ul>
*
*/
public class CSVProcessor {
//Number of characters that may be read
private static final int READ_AHEAD_LIMIT = 100_000_000;
/**
* The main method for the CSVProcessor program. Run the program with an
* empty argument list to see possible arguments.
*
* @param args the argument list for CSVProcessor.
*/
public static void main(String[] args) {
if (args.length < 2) {
printUsageAndExit();
}
try (BufferedReader br = new BufferedReader(
Files.newBufferedReader(Paths.get(args[args.length - 1])))) {
//Assume that the first line contains column names.
List<String> header = Arrays.stream(br.readLine().split(","))
.map(String::trim).collect(toList());
//Calculate an index of the column in question.
int column = getColumnNumber(header, args[1]);
switch (args[0]) {
case "sort":
verifyArgumentNumber(args, 4);
//Define the sort order.
boolean isAsc;
switch (args[2].toUpperCase()) {
case "ASC":
isAsc = true;
break;
case "DESC":
isAsc = false;
break;
default:
printUsageAndExit("Illegal argument" + args[2]);
return;//Should not be reached.
}
/*
* Create a comparator that compares lines by comparing
* values in the specified column.
*/
Comparator<String> cmp
= Comparator.comparing(str -> getCell(str, column),
String.CASE_INSENSITIVE_ORDER);
/*
* sorted(...) is used to sort records.
* forEach(...) is used to output sorted records.
*/
br.lines().sorted(isAsc ? cmp : cmp.reversed())
.forEach(System.out::println);
break;
case "search":
verifyArgumentNumber(args, 4);
/*
* Records are filtered by a regex.
* forEach(...) is used to output filtered records.
*/
Predicate<String> pattern
= Pattern.compile(args[2]).asPredicate();
br.lines().filter(str -> pattern.test(getCell(str, column)))
.forEach(System.out::println);
break;
case "groupby":
verifyArgumentNumber(args, 3);
/*
* Group lines by values in the column with collect(...), and
* print with forEach(...) for every distinct value within
* the column.
*/
br.lines().collect(
Collectors.groupingBy(str -> getCell(str, column),
toCollection(TreeSet::new)))
.forEach((str, set) -> {
System.out.println(str + ":");
set.forEach(System.out::println);
});
break;
case "stat":
verifyArgumentNumber(args, 3);
/*
* BufferedReader will be read several times.
* Mark this point to return here after each pass.
* BufferedReader will be read right after the headers line
* because it is already read.
*/
br.mark(READ_AHEAD_LIMIT);
/*
* Statistics can be collected by a custom collector in one
* pass. One pass is preferable.
*/
System.out.println(
br.lines().collect(new Statistics(column)));
/*
* Alternatively, statistics can be collected
* by a built-in API in several passes.
* This method demonstrates how separate operations can be
* implemented using a built-in API.
*/
br.reset();
statInSeveralPasses(br, column);
break;
default:
printUsageAndExit("Illegal argument" + args[0]);
}
} catch (IOException e) {
printUsageAndExit(e.toString());
}
}
private static void statInSeveralPasses(BufferedReader br, int column)
throws IOException {
System.out.println("#-----Statistics in several passes-------#");
//Create a comparator to compare records by the column.
Comparator<String> comparator
= Comparator.comparing(
(String str) -> parseDouble(getCell(str, column)));
//Find max record by using Collectors.maxBy(...)
System.out.println(
"Max: " + br.lines().collect(maxBy(comparator)).get());
br.reset();
//Find min record by using Collectors.minBy(...)
System.out.println(
"Min: " + br.lines().collect(minBy(comparator)).get());
br.reset();
//Compute the average value and sum with
//Collectors.toDoubleSummaryStatistics(...)
DoubleSummaryStatistics doubleSummaryStatistics
= br.lines().collect(summarizingDouble(
str -> parseDouble(getCell(str, column))));
System.out.println("Average: " + doubleSummaryStatistics.getAverage());
System.out.println("Sum: " + doubleSummaryStatistics.getSum());
}
private static void verifyArgumentNumber(String[] args, int n) {
if (args.length != n) {
printUsageAndExit("Expected " + n + " arguments but was "
+ args.length);
}
}
private static int getColumnNumber(List<String> header, String name) {
int column = header.indexOf(name);
if (column == -1) {
printUsageAndExit("There is no column with name " + name);
}
return column;
}
private static String getCell(String record, int column) {
return record.split(",")[column].trim();
}
private static void printUsageAndExit(String... str) {
System.out.println("Usages:");
System.out.println("CSVProcessor sort COLUMN_NAME ASC|DESC FILE");
System.out.println("Sort lines by column COLUMN_NAME in CSV FILE\n");
System.out.println("CSVProcessor search COLUMN_NAME REGEX FILE");
System.out.println("Search for REGEX in column COLUMN_NAME in CSV FILE\n");
System.out.println("CSVProcessor groupby COLUMN_NAME FILE");
System.out.println("Split lines into different groups according to column "
+ "COLUMN_NAME value\n");
System.out.println("CSVProcessor stat COLUMN_NAME FILE");
System.out.println("Compute max/min/average/sum statistics by column "
+ "COLUMN_NAME\n");
Arrays.asList(str).forEach(System.err::println);
System.exit(1);
}
/*
* This is a custom implementation of the Collector interface.
* Statistics are objects gather max,min,sum,average statistics.
*/
private static class Statistics
implements Collector<String, Statistics, Statistics> {
/*
* This implementation does not need to be thread safe because
* the parallel implementation of
* {@link java.util.stream.Stream#collect Stream.collect()}
* provides the necessary partitioning and isolation for safe parallel
* execution.
*/
private String maxRecord;
private String minRecord;
private double sum;
private int lineCount;
private final BinaryOperator<String> maxOperator;
private final BinaryOperator<String> minOperator;
private final int column;
public Statistics(int column) {
this.column = column;
Comparator<String> cmp = Comparator.comparing(
(String str) -> parseDouble(getCell(str, column)));
maxOperator = BinaryOperator.maxBy(cmp);
minOperator = BinaryOperator.minBy(cmp);
}
/*
* Process line.
*/
public Statistics accept(String line) {
maxRecord = maxRecord == null
? line : maxOperator.apply(maxRecord, line);
minRecord = minRecord == null
? line : minOperator.apply(minRecord, line);
sum += parseDouble(getCell(line, column));
lineCount++;
return this;
}
/*
* Merge two Statistics.
*/
public Statistics combine(Statistics stat) {
maxRecord = maxOperator.apply(maxRecord, stat.getMaxRecord());
minRecord = minOperator.apply(minRecord, stat.getMinRecord());
sum += stat.getSum();
lineCount += stat.getLineCount();
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("#------Statistics------#\n");
sb.append("Max: ").append(getMaxRecord()).append("\n");
sb.append("Min: ").append(getMinRecord()).append("\n");
sb.append("Sum = ").append(getSum()).append("\n");
sb.append("Average = ").append(average()).append("\n");
sb.append("#------Statistics------#\n");
return sb.toString();
}
@Override
public Supplier<Statistics> supplier() {
return () -> new Statistics(column);
}
@Override
public BiConsumer<Statistics, String> accumulator() {
return Statistics::accept;
}
@Override
public BinaryOperator<Statistics> combiner() {
return Statistics::combine;
}
@Override
public Function<Statistics, Statistics> finisher() {
return stat -> stat;
}
@Override
public Set<Characteristics> characteristics() {
return EnumSet.of(Characteristics.IDENTITY_FINISH);
}
private String getMaxRecord() {
return maxRecord;
}
private String getMinRecord() {
return minRecord;
}
private double getSum() {
return sum;
}
private double average() {
return sum / lineCount;
}
private int getLineCount() {
return lineCount;
}
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation, and proper error handling, might not be present in
* this sample code.
*/
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
/**
* Grep prints lines matching a regex. See {@link #printUsageAndExit(String...)}
* method for instructions and command line parameters. This sample shows
* examples of using next features:
* <ul>
* <li>Lambda and bulk operations. Working with streams:
* map(...),filter(...),flatMap(...),limit(...) methods.</li>
* <li>Static method reference for printing values.</li>
* <li>New Collections API forEach(...) method.</li>
* <li>Try-with-resources feature.</li>
* <li>new Files.walk(...), Files.lines(...) API.</li>
* <li>Streams that need to be closed.</li>
* </ul>
*
*/
public class Grep {
private static void printUsageAndExit(String... str) {
System.out.println("Usage: " + Grep.class.getSimpleName()
+ " [OPTION]... PATTERN FILE...");
System.out.println("Search for PATTERN in each FILE. "
+ "If FILE is a directory then whole file tree of the directory"
+ " will be processed.");
System.out.println("Example: grep -m 100 'hello world' menu.h main.c");
System.out.println("Options:");
System.out.println(" -m NUM: stop analysis after NUM matches");
Arrays.asList(str).forEach(System.err::println);
System.exit(1);
}
/**
* The main method for the Grep program. Run program with empty argument
* list to see possible arguments.
*
* @param args the argument list for Grep.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void main(String[] args) throws IOException {
long maxCount = Long.MAX_VALUE;
if (args.length < 2) {
printUsageAndExit();
}
int i = 0;
//parse OPTIONS
while (args[i].startsWith("-")) {
switch (args[i]) {
case "-m":
try {
maxCount = Long.parseLong(args[++i]);
} catch (NumberFormatException ex) {
printUsageAndExit(ex.toString());
}
break;
default:
printUsageAndExit("Unexpected option " + args[i]);
}
i++;
}
//parse PATTERN
Pattern pattern = Pattern.compile(args[i++]);
if (i == args.length) {
printUsageAndExit("There are no files for input");
}
try {
/*
* First obtain the list of all paths.
* For a small number of arguments there is little to be gained
* by producing this list in parallel. For one argument
* there will be no parallelism.
*
* File names are converted to paths. If a path is a directory then
* Stream is populated with whole file tree of the directory by
* flatMap() method. Files are filtered from directories.
*/
List<Path> files = Arrays.stream(args, i, args.length)
.map(Paths::get)
// flatMap will ensure each I/O-based stream will be closed
.flatMap(Grep::getPathStream)
.filter(Files::isRegularFile)
.collect(toList());
/*
* Then operate on that list in parallel.
* This is likely to give a more even distribution of work for
* parallel execution.
*
* Lines are extracted from files. Lines are filtered by pattern.
* Stream is limited by number of matches. Each remaining string is
* displayed in std output by method reference System.out::println.
*/
files.parallelStream()
// flatMap will ensure each I/O-based stream will be closed
.flatMap(Grep::path2Lines)
.filter(pattern.asPredicate())
.limit(maxCount)
.forEachOrdered(System.out::println);
} catch (UncheckedIOException ioe) {
printUsageAndExit(ioe.toString());
}
}
/**
* Flattens file system hierarchy into a stream. This code is not inlined
* for the reason of Files.walk() throwing a checked IOException that must
* be caught.
*
* @param path - the file or directory
* @return Whole file tree starting from path, a stream with one element -
* the path itself - if it is a file.
*/
private static Stream<Path> getPathStream(Path path) {
try {
return Files.walk(path);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* Produces a stream of lines from a file. The result is a stream in order
* to close it later. This code is not inlined for the reason of
* Files.lines() throwing a checked IOException that must be caught.
*
* @param path - the file to read
* @return stream of lines from the file
*/
private static Stream<String> path2Lines(Path path) {
try {
return Files.lines(path);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation, and proper error handling, might not be present in
* this sample code.
*/
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
/**
* Generates password of desired length. See {@link #usage} method
* for instructions and command line parameters. This sample shows usages of:
* <ul>
* <li>Method references.</li>
* <li>Lambda and bulk operations. A stream of random integers is mapped to
* chars, limited by desired length and printed in standard output as password
* string.</li>
* </ul>
*
*/
public class PasswordGenerator {
private static void usage() {
System.out.println("Usage: PasswordGenerator LENGTH");
System.out.println(
"Password Generator produces password of desired LENGTH.");
}
private static final List<Integer> PASSWORD_CHARS = new ArrayList<>();
//Valid symbols.
static {
IntStream.rangeClosed('0', '9').forEach(PASSWORD_CHARS::add); // 0-9
IntStream.rangeClosed('A', 'Z').forEach(PASSWORD_CHARS::add); // A-Z
IntStream.rangeClosed('a', 'z').forEach(PASSWORD_CHARS::add); // a-z
}
/**
* The main method for the PasswordGenerator program. Run program with empty
* argument list to see possible arguments.
*
* @param args the argument list for PasswordGenerator.
*/
public static void main(String[] args) {
if (args.length != 1) {
usage();
return;
}
long passwordLength;
try {
passwordLength = Long.parseLong(args[0]);
if (passwordLength < 1) {
printMessageAndUsage("Length has to be positive");
return;
}
} catch (NumberFormatException ex) {
printMessageAndUsage("Unexpected number format" + args[0]);
return;
}
/*
* Stream of random integers is created containing Integer values
* in range from 0 to PASSWORD_CHARS.size().
* The stream is limited by passwordLength.
* Valid chars are selected by generated index.
*/
new SecureRandom().ints(passwordLength, 0, PASSWORD_CHARS.size())
.map(PASSWORD_CHARS::get)
.forEach(i -> System.out.print((char) i));
}
private static void printMessageAndUsage(String message) {
System.err.println(message);
usage();
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation, and proper error handling, might not be present in
* this sample code.
*/
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.function.Consumer;
import java.util.regex.Pattern;
/**
* WC - Prints newline, word, and character counts for each file. See
* the {@link #usage} method for instructions and command line parameters. This
* sample shows usages of:
* <ul>
* <li>Lambda and bulk operations. Shows how to create a custom collector to
* gather custom statistics. Implements the collection of statistics using a
* built-in API.</li>
* <li>Constructor reference.</li>
* <li>Try-with-resources feature.</li>
* </ul>
*
*/
public class WC {
//The number of characters that may be read.
private static final int READ_AHEAD_LIMIT = 100_000_000;
//The pattern for splitting strings by non word characters to get words.
private static final Pattern nonWordPattern = Pattern.compile("\\W");
/**
* The main method for the WC program. Run the program with an empty
* argument list to see possible arguments.
*
* @param args the argument list for WC
* @throws java.io.IOException If an input exception occurred.
*/
public static void main(String[] args) throws IOException {
if (args.length != 1) {
usage();
return;
}
try (BufferedReader reader = new BufferedReader(
new FileReader(args[0]))) {
reader.mark(READ_AHEAD_LIMIT);
/*
* Statistics can be gathered in four passes using a built-in API.
* The method demonstrates how separate operations can be
* implemented using a built-in API.
*/
collectInFourPasses(reader);
/*
* Usage of several passes to collect data is not the best way.
* Statistics can be gathered by a custom collector in one pass.
*/
reader.reset();
collectInOnePass(reader);
} catch (FileNotFoundException e) {
usage();
System.err.println(e);
}
}
private static void collectInFourPasses(BufferedReader reader)
throws IOException {
/*
* Input is read as a stream of lines by lines().
* Every line is turned into a stream of chars by the flatMapToInt(...)
* method.
* Length of the stream is counted by count().
*/
System.out.println("Character count = "
+ reader.lines().flatMapToInt(String::chars).count());
/*
* Input is read as a stream of lines by lines().
* Every line is split by nonWordPattern into words by flatMap(...)
* method.
* Empty lines are removed by the filter(...) method.
* Length of the stream is counted by count().
*/
reader.reset();
System.out.println("Word count = "
+ reader.lines()
.flatMap(nonWordPattern::splitAsStream)
.filter(str -> !str.isEmpty()).count());
reader.reset();
System.out.println("Newline count = " + reader.lines().count());
/*
* Input is read as a stream of lines by lines().
* Every line is mapped to its length.
* Maximum of the lengths is calculated.
*/
reader.reset();
System.out.println("Max line length = "
+ reader.lines().mapToInt(String::length).max().getAsInt());
}
private static void collectInOnePass(BufferedReader reader) {
/*
* The collect() method has three parameters:
* The first parameter is the {@code WCStatistic} constructor reference.
* collect() will create {@code WCStatistics} instances, where
* statistics will be aggregated.
* The second parameter shows how {@code WCStatistics} will process
* String.
* The third parameter shows how to merge two {@code WCStatistic}
* instances.
*
* Also {@code Collector} can be used, which would be more reusable
* solution. See {@code CSVProcessor} example for how {@code Collector}
* can be implemented.
*
* Note that the any performance increase when going parallel will
* depend on the size of the input (lines) and the cost per-element.
*/
WCStatistics wc = reader.lines().parallel()
.collect(WCStatistics::new,
WCStatistics::accept,
WCStatistics::combine);
System.out.println(wc);
}
private static void usage() {
System.out.println("Usage: " + WC.class.getSimpleName() + " FILE");
System.out.println("Print newline, word,"
+ " character counts and max line length for FILE.");
}
private static class WCStatistics implements Consumer<String> {
/*
* @implNote This implementation does not need to be thread safe because
* the parallel implementation of
* {@link java.util.stream.Stream#collect Stream.collect()}
* provides the necessary partitioning and isolation for safe parallel
* execution.
*/
private long characterCount;
private long lineCount;
private long wordCount;
private long maxLineLength;
/*
* Processes line.
*/
@Override
public void accept(String line) {
characterCount += line.length();
lineCount++;
wordCount += nonWordPattern.splitAsStream(line)
.filter(str -> !str.isEmpty()).count();
maxLineLength = Math.max(maxLineLength, line.length());
}
/*
* Merges two WCStatistics.
*/
public void combine(WCStatistics stat) {
wordCount += stat.wordCount;
lineCount += stat.lineCount;
characterCount += stat.characterCount;
maxLineLength = Math.max(maxLineLength, stat.maxLineLength);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("#------WCStatistic------#\n");
sb.append("Character count = ").append(characterCount).append('\n');
sb.append("Word count = ").append(wordCount).append('\n');
sb.append("Newline count = ").append(lineCount).append('\n');
sb.append("Max line length = ").append(maxLineLength).append('\n');
return sb.toString();
}
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* The code sample illustrates the usage of default methods in the JDK 8. Most
* implementations of {@link Iterator} don't provide a useful
* {@link Iterator#remove()} method, however,
* they still have to implement this method to throw
* an UnsupportedOperationException. With the default method, the same
* default behavior in interface Iterator itself can be provided.
*/
public class ArrayIterator {
/** Close the constructor because ArrayIterator is part of the utility
* class.
*/
protected ArrayIterator() {
throw new UnsupportedOperationException();
}
/**
* Returns an iterator that goes over the elements in the array.
*
* @param <E> type of an array element
* @param array source array to iterate over it
* @return an iterator that goes over the elements in the array
*/
public static <E> Iterator<E> iterator(final E[] array) {
return new Iterator<E>() {
/**
* Index of the current position
*
*/
private int index = 0;
/**
* Returns the next element in the iteration
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more
* elements
*/
@Override
public boolean hasNext() {
return (index < array.length);
}
/**
* Returns {@code true} if the iteration has more elements. (In
* other words, returns {@code true} if {@link #next} returns
* an element, rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return array[index++];
}
/**
* This method does not need to be overwritten in JDK 8.
*/
//@Override
//public void remove() {
// throw UnsupportedOperationException(
// "Arrays don't support remove.")
//}
};
}
/**
* Sample usage of the ArrayIterator
*
* @param args command-line arguments
*/
public static void main(final String[] args) {
Iterator<String> it = ArrayIterator.iterator(
new String[]{"one", "two", "three"});
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This sample diamond interface inheritance with <b>default methods</b>.
* If there's not already a unique method implementation to inherit,
* you must provide it. The inheritance diagram is similar to the following:
* <pre>
* Animal
* / \
* Horse Bird
* \ /
* Pegasus
* </pre>
*
* Both {@link Horse} and {@link Bird} interfaces implements the <code>go</code>
* method. The {@link Pegasus} class have to overrides the
* <code>go</code> method.
*
* The new syntax of super-call is used here:
* <pre>
* &lt;interface_name&gt;.super.&lt;method&gt;(...);
* For example: Horse.super.go();
* </pre> So, Pegasus moves like a horse.
*/
public class DiamondInheritance {
/**
* Base interface to illustrate the diamond inheritance.
*
* @see DiamondInheritance
*/
public interface Animal {
/**
* Return string representation of the "go" action for concrete animal
*
* @return string representation of the "go" action for concrete animal
*/
String go();
}
/**
* Interface to illustrate the diamond inheritance.
*
* @see DiamondInheritance
*/
public interface Horse extends Animal {
/**
* Return string representation of the "go" action for horse
*
* @return string representation of the "go" action for horse
*/
@Override
default String go() {
return this.getClass().getSimpleName() + " walks on four legs";
}
}
/**
* Interface to illustrate the diamond inheritance.
*
* @see DiamondInheritance
*/
public interface Bird extends Animal {
/**
* Return string representation of the "go" action for bird
*
* @return string representation of the "go" action for bird
*/
@Override
default String go() {
return this.getClass().getSimpleName() + " walks on two legs";
}
/**
* Return string representation of the "fly" action for bird
*
* @return string representation of the "fly" action for bird
*/
default String fly() {
return "I can fly";
}
}
/**
* Class to illustrate the diamond inheritance. Pegasus must mix horse and
* bird behavior.
*
* @see DiamondInheritance
*/
public static class Pegasus implements Horse, Bird {
/**
* Return string representation of the "go" action for the fictitious
* creature Pegasus
*
* @return string representation of the "go" action for the fictitious
* creature Pegasus
*/
@Override
public String go() {
return Horse.super.go();
}
}
/**
* Illustrate the behavior of the {@link Pegasus} class
*
* @param args command line arguments
*/
public static void main(final String[] args) {
System.out.println(new Pegasus().go());
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* The sample illustrates rules to resolve conflicts between inheritance
* candidates with <b>default methods</b>. There are two simple rules:
* <ul>
* <li>Class wins. If the superclass has a concrete or abstract declaration of
* this method, then it is preferred over all defaults.</li>
* <li>Subtype wins. If an interface extends another interface, and both provide
* a default, then the more specific interface wins. </li>
* </ul>
*/
public class Inheritance {
/**
* The behavior of an creature that can swim
*/
public interface Swimable {
/**
* Return string representation of the swim action for a creature that
* can swim
*
* @return string representation of the swim action for a creature
* that can swim
*/
default String swim() {
return "I can swim.";
}
}
/**
* The abstract class that overrides {@link #swim} method
*/
public abstract static class Fish implements Swimable {
/**
* Return string representation of the swim action for a fish
*
* @return string representation of the swim action for a fish
*/
@Override
public String swim() {
return this.getClass().getSimpleName() + " swims under water";
}
}
/**
* This class is used for the illustration rule of 1. See the source code
* of the {@link #main} method.
* <pre>
* System.out.println(new Tuna().swim()); //"Tuna swims under water" output is suspected here
* </pre>
*/
public static class Tuna extends Fish implements Swimable {
}
/**
* The behavior of an creature that can dive: the interface that overrides
* {@link #swim} method (subtype of {@link Swimable})
*/
public interface Diveable extends Swimable {
/**
* Return string representation of the swim action for a creature that
* can dive
*
* @return string representation of the swim action for a creature
* that can dive
*/
@Override
default String swim() {
return "I can swim on the surface of the water.";
}
/**
* Return string representation of the dive action for a creature that
* can dive
*
* @return string representation of the dive action for a creature
* that can dive
*/
default String dive() {
return "I can dive.";
}
}
/**
* This class is used for the illustration of rule 2. See the source code
* of the {@link #main} method
* <pre>
* //"I can swim on the surface of the water." output is suspected here
* System.out.println(new Duck().swim());
* </pre>
*/
public static class Duck implements Swimable, Diveable {
}
/**
* Illustrate behavior of the classes: {@link Tuna} and {@link Duck}
*
* @param args command line arguments
*/
public static void main(final String[] args) {
// Illustrates rule 1. The Fish.swim() implementation wins
//"Tuna swims under water" is output
System.out.println(new Tuna().swim());
// Illustrates rule 2. The Diveable.swim() implementation wins
//"I can swim on the surface of the water." is output
System.out.println(new Duck().swim());
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.IOException;
import java.lang.reflect.Field;
/**
* The example illustrates how to use the default method for mixin.
* @see BuildType
* @see Debuggable
*/
public class MixIn {
/**
* Implement this interface for a class that must be in debug print
*/
public interface Debuggable {
/**
* Print the class name and all fields to a string. Uses reflection to
* obtain and access fields of this object.
*
* @return the string formatted like the following: <pre>
* State of the: &lt;Class Name&gt;
* &lt;member name&gt; : &lt;value&gt;
* ...
* </pre>
*/
default String toDebugString() {
StringBuilder sb = new StringBuilder();
sb.append("State of the: ").append(
this.getClass().getSimpleName()).append("\n");
for (Class cls = this.getClass();
cls != null;
cls = cls.getSuperclass()) {
for (Field f : cls.getDeclaredFields()) {
try {
f.setAccessible(true);
sb.append(f.getName()).append(" : ").
append(f.get(this)).append("\n");
} catch (IllegalAccessException e) {
}
}
}
return sb.toString();
}
}
/**
* Sample exception class to demonstrate mixin. This enum inherits the
* behavior of the {@link Debuggable}
*/
public static enum BuildType implements Debuggable {
BUILD(0, "-build"),
PLAN(0, "-plan"),
EXCLUDE(1, "-exclude"),
TOTAL(2, "-total");
private final int compareOrder;
private final String pathSuffix;
private BuildType(int compareOrder, String pathSuffix) {
this.compareOrder = compareOrder;
this.pathSuffix = pathSuffix;
}
public int getCompareOrder() {
return compareOrder;
}
public String getPathSuffix() {
return pathSuffix;
}
}
/**
* Illustrate the behavior of the MixClass
*
* @param args command-line arguments
* @throws java.io.IOException internal demo error
*/
public static void main(final String[] args) throws IOException {
System.out.println(BuildType.BUILD.toDebugString());
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Stream;
/**
* The code sample illustrates changes in the reflection API linked
* <b>default methods</b>. Since Java SE 8, a new method is added into the class
* <b><code>java.lang.reflect.Method</code></b>, with which you can reflectively
* determine whether or not a default method provided by an interface
* (<b><code>Method.isDefault()</code></b>).
*/
public class Reflection {
/**
* Base interface to illustrate the new reflection API.
*
* @see Dog
*/
public interface Animal {
/**
* Return string representation of the eat action for Animal
*
* @return string representation of the eat action for Animal
*/
default String eat() {
return this.getClass().getSimpleName()
+ " eats like an ordinary animal";
}
/**
* Return string representation of the sleep action for Animal
*
* @return string representation of the sleep action for Animal
*/
default String sleep() {
return this.getClass().getSimpleName()
+ " sleeps like an ordinary animal";
}
/**
* Return string representation of the go action for Animal
*
* @return string representation of the go action for Animal
*/
String go();
}
/**
* Dog class to illustrate the new reflection API. You can see that:
* <ul>
* <li> the {@link #go} and {@link #sleep} methods are not default.
* {@link #go} is not the default implementation and the {@link #sleep}
* method implementation wins as subtype (according with {@link Inheritance}
* rule. 2) </li>
* <li> the {@link #eat} is a simple default method that is not overridden
* in this class.
* </li>
* </ul>
*/
public static class Dog implements Animal {
/**
* Return string representation of the go action for Dog
*
* @return string representation of the go action for Dog
*/
@Override
public String go() {
return "Dog walks on four legs";
}
/**
* Return string representation of the sleep action for Dog
*
* @return string representation of the sleep action for Dog
*/
@Override
public String sleep() {
return "Dog sleeps";
}
}
/**
* Illustrate the usage of the method java.lang.reflect.Method.isDefault()
*
* @param args command-line arguments
* @throws NoSuchMethodException internal demo error
*/
public static void main(final String[] args) throws NoSuchMethodException {
Dog dog = new Dog();
Stream.of(Dog.class.getMethod("eat"), Dog.class.getMethod("go"), Dog.class.getMethod("sleep"))
.forEach((m) -> {
System.out.println("Method name: " + m.getName());
System.out.println(" isDefault: " + m.isDefault());
System.out.print(" invoke: ");
try {
m.invoke(dog);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
}
System.out.println();
});
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* The sample illustrates the simplest use case of the <b>default methods</b>.
*/
public class SimplestUsage {
/**
* The Animal interface provides the default implementation
* of the {@link #eat} method.
*/
public interface Animal {
/**
* Return string representation of the eat action for Animal
*
* @return string representation of the eat action for Animal
*/
default String eat() {
return this.getClass().getSimpleName()
+ " eats like an ordinary animal";
}
}
/**
* The Dog class doesn't have its own implementation of the {@link #eat}
* method and uses the default implementation.
*/
public static class Dog implements Animal {
}
/**
* The Mosquito class implements {@link #eat} method, its own implementation
* overrides the default implementation.
*
*/
public static class Mosquito implements Animal {
/**
* Return string representation of the eat action for Mosquito
*
* @return string representation of the eat action for Mosquito
*/
@Override
public String eat() {
return "Mosquito consumes blood";
}
}
/**
* Illustrate behavior of the classes: {@link Dog} and {@link Mosquito}
*
* @param args command-line arguments
*/
public static void main(String[] args) {
// "Dog eats like an ordinary animal" is output
System.out.println(new Dog().eat());
// "Mosquito consumes blood" is output
System.out.println(new Mosquito().eat());
}
}
<!DOCTYPE html>
<html>
<head>
<title>Try-with-Resources Feature Demo</title>
</head>
<body>
<h2>Try-with-Resources Feature Demo</h2>
<p>
This demo shows how to use the try-with-resources feature introduced in JDK7.
</p>
<ul>
<li><h3>Custom AutoCloseable.</h3>
<p>
Shows how to use a custom resource with the try-with-resources construct.
For more information, see the source file.
</p>
Source: <a href="src/CustomAutoCloseableSample.java">src/CustomAutoCloseableSample.java</a>
<li><h3>Unzip</h3>
<p>
Extracts archived files. For more information, see the source file.
</p>
Source: <a href="src/Unzip.java">src/Unzip.java</a>
<li><h3>ZipCat</h3>
<p>Prints data about a specified file from an archive. For more information, see the source file.</p>
Source: <a href="src/ZipCat.java">src/ZipCat.java</a>
</ul>
</body>
</html>
\ No newline at end of file
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation, and proper error handling, might not be present in
* this sample code.
*/
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* This sample demonstrates the ability to create custom resource that
* implements the {@code AutoCloseable} interface. This resource can be used in
* the try-with-resources construct.
*/
public class CustomAutoCloseableSample {
/**
* The main method for the CustomAutoCloseableSample program.
*
* @param args is not used.
*/
public static void main(String[] args) {
/*
* TeeStream will be closed automatically after the try block.
*/
try (TeeStream teeStream = new TeeStream(System.out, Paths.get("out.txt"));
PrintStream out = new PrintStream(teeStream)) {
out.print("Hello, world");
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
/**
* Passes the output through to the specified output stream while copying it into a file.
* The TeeStream functionality is similar to the Unix tee utility.
* TeeStream implements AutoCloseable interface. See OutputStream for details.
*/
public static class TeeStream extends OutputStream {
private final OutputStream fileStream;
private final OutputStream outputStream;
/**
* Creates a TeeStream.
*
* @param outputStream an output stream.
* @param outputFile an path to file.
* @throws IOException If an I/O error occurs.
*/
public TeeStream(OutputStream outputStream, Path outputFile) throws IOException {
this.fileStream = new BufferedOutputStream(Files.newOutputStream(outputFile));
this.outputStream = outputStream;
}
/**
* Writes the specified byte to the specified output stream
* and copies it to the file.
*
* @param b the byte to be written.
* @throws IOException If an I/O error occurs.
*/
@Override
public void write(int b) throws IOException {
fileStream.write(b);
outputStream.write(b);
}
/**
* Flushes this output stream and forces any buffered output bytes
* to be written out.
* The <code>flush</code> method of <code>TeeStream</code> flushes
* the specified output stream and the file output stream.
*
* @throws IOException if an I/O error occurs.
*/
@Override
public void flush() throws IOException {
outputStream.flush();
fileStream.flush();
}
/**
* Closes underlying streams and resources.
* The external output stream won't be closed.
* This method is the member of AutoCloseable interface and
* it will be invoked automatically after the try-with-resources block.
*
* @throws IOException If an I/O error occurs.
*/
@Override
public void close() throws IOException {
try (OutputStream file = fileStream) {
flush();
}
}
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation, and proper error handling, might not be present in
* this sample code.
*/
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.*;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
/**
* Extract (unzip) a file to the current directory.
*/
public class Unzip {
/**
* The main method for the Unzip program. Run the program with an empty
* argument list to see possible arguments.
*
* @param args the argument list for {@code Unzip}.
*/
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage: Unzip zipfile");
}
final Path destDir = Paths.get(".");
/*
* Create AutoCloseable FileSystem. It will be closed automatically
* after the try block.
*/
try (FileSystem zipFileSystem = FileSystems.newFileSystem(Paths.get(args[0]), null)) {
Path top = zipFileSystem.getPath("/");
Files.walk(top).skip(1).forEach(file -> {
Path target = destDir.resolve(top.relativize(file).toString());
System.out.println("Extracting " + target);
try {
Files.copy(file, target, REPLACE_EXISTING);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
} catch (UncheckedIOException | IOException e) {
e.printStackTrace();
System.exit(1);
}
}
}
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation, and proper error handling, might not be present in
* this sample code.
*/
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* Prints data of the specified file to standard output from a zip archive.
*/
public class ZipCat {
/**
* The main method for the ZipCat program. Run the program with an empty
* argument list to see possible arguments.
*
* @param args the argument list for ZipCat
*/
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: ZipCat zipfile fileToPrint");
}
/*
* Creates AutoCloseable FileSystem and BufferedReader.
* They will be closed automatically after the try block.
* If reader initialization fails, then zipFileSystem will be closed
* automatically.
*/
try (FileSystem zipFileSystem
= FileSystems.newFileSystem(Paths.get(args[0]),null);
InputStream input
= Files.newInputStream(zipFileSystem.getPath(args[1]))) {
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) != -1) {
System.out.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
}
......@@ -24,7 +24,7 @@
/**
* @test
* @bug 8032585
* @bug 8032585 8033278
* @summary JSR292: IllegalAccessError when attempting to invoke protected method from different package
*
* @compile p1/T2.java p2/T3.java
......
......@@ -23,8 +23,57 @@
*/
package p1;
import p2.T3;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.util.concurrent.Callable;
class T1 {
protected void m() { System.out.println("T1.m");}
protected void m1() {}
protected static void m2() {}
}
public class T2 extends T1 {}
public class T2 extends T1 {
public static void main(String[] args) throws Throwable {
Lookup LOOKUP = T3.lookup();
Class<IllegalAccessException> IAE = IllegalAccessException.class;
assertFailure(IAE, () -> LOOKUP.findVirtual(T1.class, "m1", MethodType.methodType(void.class)));
assertFailure(IAE, () -> LOOKUP.findStatic(T1.class, "m2", MethodType.methodType(void.class)));
assertSuccess(() -> LOOKUP.findVirtual(T2.class, "m1", MethodType.methodType(void.class)));
assertSuccess(() -> LOOKUP.findVirtual(T3.class, "m1", MethodType.methodType(void.class)));
assertSuccess(() -> LOOKUP.findStatic(T2.class, "m2", MethodType.methodType(void.class)));
assertSuccess(() -> LOOKUP.findStatic(T3.class, "m2", MethodType.methodType(void.class)));
assertFailure(IAE, () -> LOOKUP.unreflect(T1.class.getDeclaredMethod("m1")));
assertFailure(IAE, () -> LOOKUP.unreflect(T1.class.getDeclaredMethod("m2")));
System.out.println("TEST PASSED");
}
public static void assertFailure(Class<? extends Throwable> expectedError, Callable r) {
try {
r.call();
} catch(Throwable e) {
if (expectedError.isAssignableFrom(e.getClass())) {
return; // expected error
} else {
throw new Error("Unexpected error type: "+e.getClass()+"; expected type: "+expectedError, e);
}
}
throw new Error("No error");
}
public static void assertSuccess(Callable r) {
try {
r.call();
} catch(Throwable e) {
throw new Error("Unexpected error", e);
}
}
}
......@@ -25,13 +25,8 @@ package p2;
import p1.T2;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class T3 extends T2 {
public static void main(String[] args) throws Throwable {
MethodHandles.lookup().findVirtual(T3.class, "m", MethodType.methodType(void.class));
System.out.println("TEST PASSED");
}
public static MethodHandles.Lookup lookup() { return MethodHandles.lookup(); }
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册