Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

ブラウザのスクリーンショット取得を禁止する調達仕様の例

ちょっと古いが、「厚生労働省LANシステムの更改整備及び運用・保守業務」で、iOSおよびAndroidスクリーンショット取得を禁止する仕様が盛り込まれていた。 しかもRFPに元々入っていた仕様じゃなくて、意見招請で追加された仕様みたい。下記資料の番号344に記載がある。 https://www.mhlw.go.jp/sinsei/chotatu/chotatu/pdf/ikenshousei170316-02.pdf

Difference of way to get Java version at runtime

# JDK Way to launch SourceVersion.latestSupported() Runtime.class.getPackage().getImplementationVersion() Runtime.version() System.getProperty("java.version") System.getProperty("java.specification.version")
1 JDK8 java RELEASE_8 1.8.0_312 java.lang.NoSuchMethodError: java.lang.Runtime.version()Ljava/lang/Runtime$Version; 1.8.0_312 1.8
2 JDK9 java RELEASE_9 null 9.0.4+11 9.0.4 9
3 JDK10 java RELEASE_10 null 10.0.2+13 10.0.2 10
4 JDK11 java RELEASE_11 null 11.0.15+10-Ubuntu-0ubuntu0.20.04.1 11.0.15 11
5 JDK11 java --source 8 RELEASE_11 null org/example/Main.java:10: error: cannot find symbol 11.0.15 11
6 JDK17 java RELEASE_17 null 17.0.3+7-Ubuntu-0ubuntu0.20.04.1 17.0.3 17
7 JDK17 java --source 8 RELEASE_17 null org/example/Main.java:10: error: cannot find symbol 17.0.3 17
8 JDK17 java --source 11 RELEASE_17 null 17.0.3+7-Ubuntu-0ubuntu0.20.04.1 17.0.3 17
  • Runtime.version is not available in CodeChef.
  • SourceVersion is not available in many online IDEs like ideone, paiza.io, Tech.io, repl.it, JDoodle, sololearn, GeeksforGeeks.
  • All these properties are available in Wandbox.
  • Note that System.getProperty("java.vm.version") or ManagementFactory.getRuntimeMXBean().getVmVersion() are not suitable to get the version of Java runtime. It returns the VM build number rather than the version of JDK in some environments. For example, it returns 25.312-b07 in OpenJDK 1.8.0_312 (OpenJDK 64-Bit Server VM (build 25.312-b07)).

ファイルダウンロードを中断すると何が起こるか

Spring Boot 2.7.0で組み込みTomcatでアプリケーションを起動した場合、ファイルダウンロードがブラウザから中断(キャンセル)されるとClientAbortExceptionが発生する。 以前はSocketExceptionが発生していたように思うのですが、Servletコンテナによって挙動が違うのかな?

    @RequestMapping("/testDownload")
    String download(HttpServletResponse response) throws InterruptedException {
        try (OutputStream os = response.getOutputStream()) {
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=test.obj");
            byte[] b = new byte[100000];
            while (true) {
                SecureRandom sr = new SecureRandom();
                sr.nextBytes(b);
                os.write(b);
                os.flush();
                Thread.sleep(10000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

で、ダウンロードを中断すると以下の例外が返る。

org.apache.catalina.connector.ClientAbortException: java.io.IOException: 確立された接続がホスト コンピューターのソウトウェアによって中止されました。
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:353)
    at org.apache.catalina.connector.OutputBuffer.appendByteArray(OutputBuffer.java:753)
    at org.apache.catalina.connector.OutputBuffer.append(OutputBuffer.java:682)
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:388)
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:366)
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:96)
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:89)
    at com.example.sessionsize.SessionSizeController.download(SessionSizeController.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: 確立された接続がホスト コンピューターのソウトウェアによって中止されました。
    at sun.nio.ch.SocketDispatcher.write0(Native Method)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
    at sun.nio.ch.IOUtil.write(IOUtil.java:65)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
    at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:135)
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1384)
    at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:773)
    at org.apache.tomcat.util.net.SocketWrapperBase.writeBlocking(SocketWrapperBase.java:593)
    at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:537)
    at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.doWrite(Http11OutputBuffer.java:547)
    at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:112)
    at org.apache.coyote.http11.Http11OutputBuffer.doWrite(Http11OutputBuffer.java:194)
    at org.apache.coyote.Response.doWrite(Response.java:615)
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:340)
    ... 61 more

Way to shutdown Windows

There are so many ways to shutdown Windows:

# How to shutdown What is executed Wait for HungAppTimeout
1 shutdown from Start Menu RuntimeBroker.exe Yes
2 shutdown from the lock screen winlogon.exe No
3 execute SlideToShutDown.exe SlideToShutDown.exe Yes
4 execute shutdown.exe shutdown.exe No
5 execute Stop-Computer cmdlet WmiPrvSE.exe Yes
6 execute Restart-Computer cmdlet WmiPrvSE.exe Yes
7 execute Get-CimInstance -ClassName Win32_OperatingSystem | Invoke-CimMethod -MethodName Shutdown WmiPrvSE.exe No
8 Alt+F4 on Desktop Explorer.exe Yes
9 push the power button shortly winlogon.exe Yes

What is executed:

The shutdown is recorded in the Event Viewer (search for events that have the Event ID 1074 in [Windows Log]-[System]). These events have the path of the executed program to shutdown in <EventData> tag.

Wait for HungAppTimeout

As a typical example, shutdown.exe doesn't wait for the termination of applications before shutdown the system. This behavior is not suitable for the application triggered by shutdown (for example, attendance management application). On the other hand, Stop-Computer waits for the termination.

Note that this behavior is difficult to observe outside of the application (You have to intentionally hang up some applications and observe the behavior of shutdown). The result in the table above probably contains some inaccuracies. I need the information to how to observe this behavior accurately.

著作権法のコーナーケースに関する理解の度合い

たとえば「次のうち、『やっちゃいけないよ』と他の人に言ったほうがいいのはどれでしょう?」「次のうち、『やっちゃいけないよ』と他の人に言えないのはどれでしょう?」と言われて正しく答えられる人がどれだけいるか、みたいな調査って行われてるんだろうか?

自分の行動だったら「著作権がこわいからやらないでおこう」という判断ができるけど、それを他の人に言えるかというとまた違うだろうからね。

Blu-rayディスクのジャケット画像をスマホの待ち受けにする

  1. AmazonのサイトにあるBlu-rayディスクのジャケット画像を、自分のスマホの待ち受けにした。
  2. AmazonのサイトにあるBlu-rayディスクのジャケット画像を、スマホの待ち受けにする方法を友達に教えた。
  3. AmazonのサイトにあるBlu-rayディスクのジャケット画像を、自分のスマホの待ち受けにしていたので、その画像を友達にも送ったが、その友達はイマイチだと思って待ち受けには設定しなかった。
  4. AmazonのサイトにあるBlu-rayディスクのジャケット画像を、自分のスマホの待ち受けにしていたので、その画像を友達にも送って待ち受けにした。

無断転載禁止と書かれたイラストを転載する

  1. 無断転載禁止と書かれたイラストがpixivに掲載されていたので、転載したい旨のメールをpixivの運営に送ったうえで自分のTwitterアカウントに投稿した。
  2. 無断転載禁止と書かれたイラストがpixivに掲載されていたので、転載したい旨のメールをイラストの作者に送ったうえで自分のTwitterアカウントに投稿した。
  3. 無断転載禁止と書かれたイラストがpixivに掲載されていたので、転載したい旨のメールをイラストの作者に送った。作者が返事を返せるよう十分な期間をとったうえで、返信がなかったので自分のTwitterアカウントに投稿した。
  4. 無断転載禁止と書かれたイラストがpixivに掲載されていたので、転載したい旨のメールをイラストの作者に送った。OKとの返事が来たので、自分のTwitterアカウントに自分の描いたイラストとして投稿した。
  5. 無断転載禁止と書かれたイラストがpixivに掲載されていたので、転載したい旨のメールをイラストの作者に送った。OKとの返事が来たので、自分のTwitterアカウントに作者の名前といっしょに投稿した。

「違う、そうじゃない」の画像をTwitterの投稿に表示する

  1. Twitterでリプライによく使われている、鈴木雅之「違う、そうじゃない」のCDジャケットの画像をTwitterから保存しておいて、自分のTwitterの投稿で添付画像に設定した。
  2. Twitterでリプライによく使われている、鈴木雅之「違う、そうじゃない」のCDジャケットの画像を、CDを販売しているAmazonのサイトから保存しておいて、自分のTwitterの投稿で添付画像に設定した。
  3. 自分のTwitterの投稿に、Amazon鈴木雅之「違う、そうじゃない」の商品ページのURLを含めてツイートした(※Twitterの仕様として、Amazonの商品へのリンクを含むツイートは商品画像がツイートに含めて表示される)。
  4. 鈴木雅之「違う、そうじゃない」のCDジャケットと同じポーズの写真を自分で撮影して、自分のTwitterの投稿で添付画像に設定した。
  5. 鈴木雅之「違う、そうじゃない」のCDジャケットと同じポーズをしているウェズリー・スナイプスのイラストを自分で描いて、自分のTwitterの投稿で添付画像に設定した。