COOKIES! This blog uses cookies!
I am completely out of control of cookies here, otherwise I would have disabled them (it is controlled by the platform).
If you don't like cookies and being tracked please leave this blog immediately.

Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Wednesday, 26 August 2020

Set rotation period to NEVER for all crypto keys in one Google KMS keyring

Sometimes when a number of crypto keys was created it's needed to prevent them from generating new versions. See also How to delete all key versions in Google KMS keyring


 

import com.google.cloud.kms.v1.CryptoKey;

import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.kms.v1.KeyRingName;
import com.google.protobuf.Duration;
import com.google.protobuf.FieldMask;
import com.google.protobuf.util.FieldMaskUtil;

import java.io.IOException;

public class Cleanup {

private static final String KMS_PROJECT_ID = "my-dev-project";
private static final String KMS_LOCATION = "global";
private static final String KMS_KEYRING = "encrypted-values";

public static void main(String[] args) {
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
String keyRingName = KeyRingName.format(KMS_PROJECT_ID, KMS_LOCATION, KMS_KEYRING);
for (CryptoKey cryptoKey : client.listCryptoKeys(keyRingName).iterateAll()) {
String name = cryptoKey.getName();
Duration rotation = cryptoKey.getRotationPeriod();
if (rotation.getNanos() != 0 || rotation.getSeconds() != 0) {
System.out.println("Clearing rotation period of " + name);
CryptoKey updatedKey = CryptoKey.newBuilder(cryptoKey)
.clearRotationPeriod()
.clearNextRotationTime()
.build();
FieldMask fieldMask = FieldMaskUtil.fromString("rotation_period,next_rotation_time");
client.updateCryptoKey(updatedKey, fieldMask);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

}

Wednesday, 14 August 2019

Delete all key versions in Google KMS keyring

After some experiments with Google KMS I found that I have a few thousands keys created. Unfortunately there's no option in the google cloud console to destroy all keys in the key ring, the only thing possible to do is to "Disable all key versions" on each version by hand, which is not very exciting job to do with thousands of them. After short thinking I came out with the following simple java program which destroying all key versions in the keyring:

import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.kms.v1.KeyRingName;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

public class CleanupKmsKeys {

private static final String KMS_PROJECT_ID = "my-development-project";

private static final String KMS_LOCATION = "global";

private static final String KMS_KEYRING = "encrypted-values";
// Destroy all key versions in {@link #KMS_KEYRING}
public static void
main(String[] args) { String keyRingName = KeyRingName.format(KMS_PROJECT_ID, KMS_LOCATION, KMS_KEYRING); warinig(keyRingName); AtomicInteger keyCount = new AtomicInteger(0); AtomicInteger keyVersionCount = new AtomicInteger(0); try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { client.listCryptoKeys(keyRingName).iterateAll().forEach(cryptoKey -> { String name = cryptoKey.getName(); client.listCryptoKeyVersions(name).iterateAll().forEach(cryptKeyVer -> { if ( !cryptKeyVer.hasDestroyTime() && !cryptKeyVer.hasDestroyEventTime() ) { String cryptoKeyVersionName = cryptKeyVer.getName(); client.destroyCryptoKeyVersion(cryptoKeyVersionName); System.out.println(String.format( "Destroyed version %s of key %s", name, cryptoKey )); keyVersionCount.getAndIncrement(); } }); keyCount.getAndIncrement(); }); System.out.println(String.format( "Deleted %d keys and %d versions", keyCount.get(), keyVersionCount.get() )); } catch (IOException e) { System.out.println(String.format( "Failed to delete all versions, deleted %d keys and %d versions", keyCount.get(), keyVersionCount.get() )); throw new RuntimeException("Failed to destroy KMS keys"); } } private static void warinig(String keyRingName) { try { System.out.println(String.format( "I'm going to destroy all keys in %s", keyRingName )); Thread.sleep(1000); System.out.println("In 3 seconds"); Thread.sleep(1000); System.out.println("In 2 seconds"); Thread.sleep(1000); System.out.println("In 1 second"); Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException("Something went wrong"); } } }

Tuesday, 30 July 2019

Running unit tests in idea with Pattern

For some reason it's not quite documented what the "Test Kind: Pattern" in the test run configuration of the IntelliJ IDEA.
It is simply a regex expression for the classname, for example if it's needed to run all classes in the module ending up with Test then the Pattern should be the following regular expression:

^.*Test$

Friday, 5 January 2018

wicket:message with links and labels inside

wicket:message can contain markup inside of itself. It is an easy thing to do, but not quite obvious that it's allowed to do that.

For example wicket:message with a link and a label:

MyPanel.html
<wicket:message key="myMessage">
    <span wicket:id="myLabel" />
    <a wicket:id="myLink" />
</wicket:message>

MyPanel.java
//...
add(new Label("myLabel", myLabelModel));
add(new LabelledBookmarkablePageLink("myLink", ViewSomethingPage.class));
//...

MyPanel.properties
myMessage = a text before a label ${myLabel}, between label and a link ${myLink}, after link
myLink= My Link Text

${myLabel} and ${myLink} of myMessage will be replaced with appropriate components

Friday, 21 April 2017

Building less from ANT without funny plugins

There are a few libraries from non-trustworthy individual developers which do compile LESS style-sheets in java, most of them are not very transparent: some of them download node.js, some of them use rhino. It is possible to do it in clear, obvious way from your ant build, see the example for Windows below.

Properties to be defined:
${your.extensions.dir} - is some dir to put NodeJS to;
${your.web.sources.dir} - is a dir for static web files, to put CSS into.

This config downloads NodeJS, installs LESS locally and compiles styles.
This example has version for Windows and MacOS, Linux version should be similar to MacOs. Node.JS can also be installed with system package manager, `_install_node` task is not needed in this case.
05 Jan 2018: updated with MacOS executables

<!-- Build less stylesheets -->
<property name="nodejs.dir" location="${your.extensions.dir}/nodejs"/>
<!-- maybe these versions should go to the ivysettings.xml, maybe not because they are not from the maven/ivy -->
<property name="nodejs.ver" value="8.9.1"/>
<property name="less.ver" value="2.7.2"/>
<if>
  <os family="windows" />
  <then>
    <property name="nodejs.archive" value="node-v${nodejs.ver}-win-x86.zip" />
    <property name="nodejs.exec.dir" location="${nodejs.dir}/node-v${nodejs.ver}-win-x86"/>
    <property name="lessc.exec" location="${nodejs.exec.dir}/lessc.cmd"/>
  </then>
  <elseif>
    <os family="mac" />
    <then>
      <property name="nodejs.archive" value="node-v${nodejs.ver}-darwin-x64.tar.gz" />
      <property name="nodejs.exec.dir" location="${nodejs.dir}/node-v${nodejs.ver}-darwin-x64/bin"/>
      <property name="lessc.exec" location="${nodejs.exec.dir}/node_modules/.bin/lessc"/>
    </then>
  </elseif>
  <else>
      <echo message="Unsupported platform, check _install_node in build.xml"/>
  </else>
</if>

<property name="less.dir" value="${your.web.sources.dir}/com/company/web/include" />

<echo message="${nodejs.exec.dir}"/>
<target name="_install_node">
    <if>
        <not><available file="${nodejs.exec.dir}"/></not>
        <then>
            <echo message="installing nodejs..."/>
            <mkdir dir="${nodejs.dir}"/>
            <get src="https://nodejs.org/dist/v${nodejs.ver}/${nodejs.archive}" dest="${nodejs.dir}" usetimestamp="false"/>
            <if>
              <os family="windows" />
              <then>
                  <unzip src="${nodejs.dir}/${nodejs.archive}" dest="${nodejs.dir}/"> </unzip>
              </then>
              <elseif>
                <os family="mac" />
                <then>
                   <untar src="${nodejs.dir}/${nodejs.archive}" dest="${nodejs.dir}/" compression="gzip"> </untar>
                   <chmod dir="${nodejs.exec.dir}" perm="ugo+rx" includes="*"/>
                </then>
              </elseif>
              <else>
                  <echo message="Unsupported platform, check _install_node in build.xml"/>
              </else>
            </if>

        </then>
        <else>
          <echo message="nodejs already installed in ${nodejs.exec.dir}"/>
        </else>
    </if>
</target>

<target name="_install_node_less" depends="_install_node">
  <if>
      <not><available file="${lessc.exec}"/></not>
      <then>
          <echo message="installing less for node from npm..."/>
          <exec dir="${nodejs.exec.dir}" executable="cmd" osfamily="Windows">
              <arg value="/c"/>
              <arg value="${nodejs.exec.dir}/npm.cmd"/>
              <arg value="install"/>
              <arg value="less@${less.ver}"/>
          </exec>
          <exec dir="${nodejs.exec.dir}" executable="npm" osfamily="mac">
              <arg value="install"/>
              <arg value="less@${less.ver}"/>
          </exec>
      </then>
  </if>
</target>

<target name="generate-styles" depends="_install_node_less">
    <echo message="compiling less to ${less.dir} ..."/>
    <!-- win executable -->
    <exec dir="${nodejs.exec.dir}" executable="cmd" osfamily="windows">
        <arg value="/c"/>
        <arg value="${lessc.exec}"/>
        <arg value="${less.dir}/base-style.less"/>
        <arg value="${less.dir}/base-style.css"/>
        <arg value="--source-map"/>
    </exec>
    <!-- mac executable -->
     <exec dir="${nodejs.exec.dir}" executable="/bin/sh" osfamily="mac">
        <arg value="-c"/>
        <arg value="${lessc.exec} --source-map ${less.dir}/base-style.less ${less.dir}/base-style.css"/>
    </exec>
</target>

Wednesday, 15 February 2017

Spring's Autowired things to be available in constructor of JPA entity


Entities are normally not eligible for Spring-driven configuration, however it is possible to make them eligible by adding `@org.springframework.beans.factory.annotation.Configurable` annotation.

Unfortunately autowired things are not available in constructor, because they are injected after the object is constructed. Luckely `Configurable` has very useful `boolean preConstruction() default false` option to make autowired fields available in constructor. Here's the example:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.ApplicationEventPublisher;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Configurable(preConstruction = true)
public class MyEntity {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;

    private String field;

    @Autowired
    private transient ApplicationEventPublisher publisher;

    public MyEntity() {
        System.out.println("do something...");
        // publisher will be null at this point
        // if preConstruction = true is not used
        publisher.publishEvent("Publish something");
        /* ... more code ... */
    }

    /* ... your code here ... */
}

Tuesday, 26 January 2016

OpenJDK finally ported to iOS

Someone Johan has recently "run an application using Gluon Charm (Material Design UI controls) on top
of JavaFX (OpenJFX 9) on top of Java on my iPad mini, so this is a real-world complete stack."

MobileJDK is still under heavy development, however it is a good result! Port to is achieved with Zero interpreter due to the fact that Apple does not allow dynamic code generation on iOS.

Monday, 17 August 2015

Reading XLSX on Android 5+

New Android Build Tools (21+) and Android 5 (ART) seems to easily fix the problem with 65K methods for Apache POI.

All you need to do is to copy the following files into libs dir of your project:
poi-3.12-20150511.jar
poi-ooxml-3.12-20150511.jar
poi-ooxml-schemas-3.12-20150511.jar
stax-1.2.0.jar
stax-api-1.0.1.jar
xmlbeans-2.6.0.jar - the hero of the day, this jar is deffective in maven repo, so it's needed to repack this jar.

See also the repo with repacked POI 3.12 jars and gradle config examples: https://github.com/andruhon/android5xlsx


Add the following into your app/build.gradle to compile your project with multi-dex to fix 65K method's limit and --core-library, to avoid the warning about javax namespace in your libs.
apply plugin: 'com.android.application'

android {
    // ...your other project settings...
    project.tasks.withType(com.android.build.gradle.tasks.Dex) {
        additionalParameters=['--core-library']
    }
}
dependencies {
    // ...deps settings...
    compile 'com.android.support:multidex:1.0.0' //enable multi-dex
}

You still might want to do a 'aavax' hack, to avoid conflicts with future android releases.

If xmlbeans not broken it would be possible to achieve the same results with just adding 'org.apache.poi:poi-ooxml:3.12' into dependencies, however it will not work straighforwardly because xmlbeans jar in maven is defective and contains duplicates of classes, these duplicates are ok for desktop JVM, but android chokes with them. So it is required to add some routine to re-pack xmlbeans and disable preDex. It will work. however the build process will be quite slow, so it is easier just to prepare jars once and put them into libs directory (as described above)

Special thanks to Heiko Johann for pointing onto new Android Build Tools features

Links:
https://github.com/andruhon/android5xlsx - config example
https://developer.android.com/tools/revisions/build-tools.html
https://developer.android.com/tools/building/multidex.html
http://www.docx4java.org/trac/docx4j - another project of reading OpenXML from Java

Previous posts:
http://blog.kondratev.pro/2014/08/reading-xlsx-on-android.html
http://blog.kondratev.pro/2014/09/further-to-my-post-from-yesterday-on.html
http://blog.kondratev.pro/2014/09/reading-xlsx-on-android-3.html

Monday, 9 March 2015

Sending iOS push notifications from JAVA

This post was originally posted in 2015 and most likely to be irrelevant today. 
It remains published solely for historic reasons.

This example presumes that you've already registered your device for Push Notifications and retrieved the device token from the Apple Push Notification Service (APNS) on the iOS side.
The code below uses the notnoop/java-apns Java library to send notifications to the APNS server.

The code

Suggested files structure:
src/main/java/PushNotifications.java - simple java class to send notifications
src/main/resources/dev_cert.p12 - development certificate
src/main/resources/prod_cert.p12 - production certificate
pom.xml - maven config

pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>PushNotifications</groupId>
    <artifactId>PushNotifications</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>com.notnoop.apns</groupId>
            <artifactId>apns</artifactId>
            <version>1.0.0.Beta6</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.7</version>
        </dependency>
    </dependencies>

</project>

PushNotifications.java:
import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
import com.notnoop.apns.ApnsServiceBuilder;

public class PushNotifications {

    public static void main(String [] args) {
        System.out.println("Sending an iOS push notification...");

        String token = "";
        String type = "dev";
        String message = "the test push notification message";

        try {
            token = args[0];
        } catch (Exception e) {
            System.out.println("Usage: PushNotifications devicetoken [message] [type prod|dev]");
            System.out.println("example: PushNotifications 1testdevicetoken3eb414627e78991ac5a615b4a2a95454c6ba5d18930ac137 'hi there!' prod");
            return;
        }
        try {
            message = args[1];
        } catch (Exception e) {
            System.out.println("no message defined, using '"+message+"'");
        }
        try {
            type = args[2];
        } catch (Exception e) {
            System.out.println("no API type defined, using "+type);
        }

        System.out.println("The target token is "+token);

        ApnsServiceBuilder serviceBuilder = APNS.newService();

        if (type.equals("prod")) {
            System.out.println("using prod API");
            String certPath = PushNotifications.class.getResource("prod_cert.p12").getPath();
            serviceBuilder.withCert(certPath, "password")
                    .withProductionDestination();
        } else if (type.equals("dev")) {
            System.out.println("using dev API");
            String certPath = PushNotifications.class.getResource("dev_cert.p12").getPath();
            serviceBuilder.withCert(certPath, "password")
                    .withSandboxDestination();
        } else {
            System.out.println("unknown API type "+type);
            return;
        }

        ApnsService service = serviceBuilder.build();


        //Payload with custom fields
        String payload = APNS.newPayload()
                .alertBody(message)
                .alertTitle("test alert title")
                .sound("default")
                .customField("custom", "custom value").build();

        ////Payload with custom fields
        //String payload = APNS.newPayload()
        //        .alertBody(message).build();

        ////String payload example:
        //String payload = "{\"aps\":{\"alert\":{\"title\":\"My Title 1\",\"body\":\"My message 1\",\"category\":\"Personal\"}}}";


        System.out.println("payload: "+payload);
        service.push(token, payload);

        System.out.println("The message has been hopefully sent...");
    }
}
Compile the code:
>mvn compile

Run the code:
>mvn exec:java -Dexec.mainClass="PushNotifications" -Dexec.args="1testdevicetoken3eb414627e789ba5d18930ac137 'My test iOS push notification!' dev"

Getting certificates from the Apple
Certificates are quite tricky and confusing part of iOS push notifications.

1. First of all we need to create a SigningRequest
Keychain Access -> Certificate Assistant -> Request a certificate from a Certificate Authority
Enter the apple dev email into the Certificate Assistant form, select the "Save to disk" radio
Save the Signing Request onto the disk (don't forget to give it some reasonable name);

2. Go to the developer.apple.com/account/ios/
Certificates, Identifiers & Profiles > App IDs > [the app id] > Edit > Push notifications >
Production SSL Certificate > Create / Create Additional,
ensure that Push Notifications enabled for your app,
Generate a new certificate using the SigningRequest from 1.
Download the generated certificate;

3. (on the Mac) Double click the certificate to import into the keychain;

4. Locate the Certificate in the Keychain Access, expand it to see the Key inside,
right click and Export "keyname"...
Save the p12 file;

5. Notice that after regenerating your certificates you need to refresh your provisioning profiles and use them to deploy your app. In xCode go to Preferences -> Accounts, selet your dev apple-id, click "View Details", do refresh. It is not going to be a problem, if you generated the certeficates before getting to code.

Friday, 20 February 2015

Get document PDF preview in Alfresco

Alfresco is able to transform document types.
For example transform MSWord doc file into PDF

The quick way to access PDF preview (or of any other available type) is a ThumbnailService

An example:
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
//...
public class YourClass{
  //...
  @Autowired
  ThumbnailService thumbnailService;
  //...
  public yourMethod {
      NodeRef documentNodeRef = new NodeRef(
          request.getParameter("nR")
      );
      NodeRef pdfPreviewNodeRef = null;
      //...
      pdfPreviewNodeRef = thumbnailService.getThumbnailByName(
          documentNodeRef, ContentModel.PROP_CONTENT, "pdf"
      );
      if (pdfPreviewNodeRef==null) {
        //generate a new PDF preview if one is not available yet
        pdfPreviewNodeRef = thumbnailService.createThumbnail(
            documentNodeRef, ContentModel.PROP_CONTENT,
            "application/pdf", new SWFTransformationOptions(), "pdf"
        );
      }
      //...
  }
  //...
}

Saturday, 6 September 2014

Reading XLSX on android 4 (Post 3)

!!!UPDATE:
All this hacking is getting redundant with Android Build Tools 21+ and Android 5, please see this post for details: http://blog.kondratev.pro/2015/08/reading-xlsx-on-android-4-and-hopefully.html
-----------------


More on reading XLSX on Android.

I renamed "javax" namespace to "aavax" in StAX sources and recompiled it. After that I replaced all strings 'javax/xml/stream', 'javax/xml/namespace' and 'javax.xml.strings' occurrences in other binaries(including ooxml-schemas) to appropriate strings with "aavax". Now it works without necessity to use --core-library option!

Two previous posts:
http://blog.kondratev.pro/2014/08/reading-xlsx-on-android.html
http://blog.kondratev.pro/2014/09/further-to-my-post-from-yesterday-on.html

You can review demo project here:
https://github.com/andruhon/AndroidReadXLSX

You can download ported XSSX here:
https://github.com/andruhon/AndroidReadXLSX/tree/master/libs

Donate / help
I don't ask for a donation, but you can join me on the LinkedIN and endorse my Java and Android skills if you find this hack useful:
https://nz.linkedin.com/pub/andrei-kondratev/51/445/635

Tuesday, 2 September 2014

Reading XLSX on android 4 (Post 2)

!!!UPDATE:
All this hacking is getting redundant with Android Build Tools 21+ and Android 5, please see this post for details: http://blog.kondratev.pro/2015/08/reading-xlsx-on-android-4-and-hopefully.html
-----------------

Further to my post from Saturday on reading XLSX on Android:

I shrunk dom4j, poi, poi-ooxml and xmlbeans into one jar with proguard. All classes not necessary for reading Excel files are seems to be removed. Proguard config follows:

-injars      {my IN jars mentioned above}
-outjars     poi-min.jar

-libraryjars {my dir with schemas}
-libraryjars {path to /jre/lib}
-libraryjars {path to /jdk/lib}

-dontoptimize
-dontobfuscate
-ignorewarnings

-keep class org.apache.poi.xssf.** { *; }
-keep class org.apache.poi.ss.** { *; }
-keep class org.apache.poi.hssf.** { *; }
-keep class org.apache.xmlbeans.** { *; }

It works fine for reading and writing both XLS and XLSX files.

Next post on XLSX:
http://blog.kondratev.pro/2014/09/reading-xlsx-on-android-3.html

Previous post on XLSX:
http://blog.kondratev.pro/2014/08/reading-xlsx-on-android.html

Sunday, 31 August 2014

Reading XLSX on android 4 (Post 1)

!!!UPDATE:
All this hacking is getting redundant with Android Build Tools 21+ and Android 5, please see this post for details: http://blog.kondratev.pro/2015/08/reading-xlsx-on-android-4-and-hopefully.html
-----------------

Yesterday I committed XSSF Android usage demo to github:
https://github.com/andruhon/AndroidReadXLSX
The idea is in cleaning jars poi-ooxml and poi-ooxml-schemas from everything which is not necessary to read XLSX format. (just use ZIP archiver to manipulate classes inside, it works well)
This demo already contains reduced poi-ooxml-3.10-reduced.jar and poi-ooxml-schemas-3.10-reduced-more.jar and short building instructions.
Yep, you should use --core-library option to build this project. poi-ooxml depends on xmlbeans and both of them depends on some javax classes which are not available in android. So I have to use StAX library.
UPD: no need in --core-library option any more!

Other posts on reading XLSX on Android:
http://blog.kondratev.pro/2014/09/further-to-my-post-from-yesterday-on.html
http://blog.kondratev.pro/2014/09/reading-xlsx-on-android-3.html

Donate / help
I don't ask for a donation, but you can join me on the LinkedIN and endorse my Java and Android skills if you find this hack useful:
https://nz.linkedin.com/pub/andrei-kondratev/51/445/635